Buffer is not defined in React-vite - reactjs

Buffer is not defined after migrating from CRA(create react app)
"vite": "^2.7.12"
I try to add plugins, add define for Buffer, but it's not work.
const viteConfig = defineConfig({
/* define: {
"Buffer": {}
},*/
plugins: [reactRefresh(), react()],
build: {
rollupOptions: {
input: {
main: resolve('index.html'),
},
},
},
clearScreen: false
});

Install this library
#esbuild-plugins/node-globals-polyfill
and add this in your vite.config.js
export default defineConfig({
// ...other config settings
optimizeDeps: {
esbuildOptions: {
// Node.js global to browser globalThis
define: {
global: 'globalThis'
},
// Enable esbuild polyfill plugins
plugins: [
NodeGlobalsPolyfillPlugin({
buffer: true
})
]
}
}
})
add this libary import to your vite.config.js
import { NodeGlobalsPolyfillPlugin } from '#esbuild-plugins/node-globals-polyfill'

Николай Сычев solution didn't work for me at first.
Instead, I succeeded by simply
installing buffer as a dev dependency
yarn add buffer (use npm equivalent if you use npm)
and then adding it to the global scope in the index.html like this:
<html lang="en">
<head>
<script type="module">
import { Buffer } from "buffer";
window.Buffer = Buffer;
</script>
...
It also works for similar dependencies like process which you'd import in the index.html like this:
import process from "process";
window.process = process;
Update
For a different project I needed util, which required process. The above suggested method didn't suffice in that case.
Instead I found out that #esbuild-plugins (for vite dev) and rollup-plugin-polyfill-node (for vite build) would successfully provide all these nodejs packages.
Here is a full vite.config.ts that works for me:
import { defineConfig } from 'vite'
import vue from '#vitejs/plugin-vue'
import { NodeGlobalsPolyfillPlugin } from '#esbuild-plugins/node-globals-polyfill'
import { NodeModulesPolyfillPlugin } from '#esbuild-plugins/node-modules-polyfill'
import rollupNodePolyFill from 'rollup-plugin-polyfill-node'
export default defineConfig({
plugins: [vue()],
base: '',
optimizeDeps: {
esbuildOptions: {
// Node.js global to browser globalThis
define: {
global: 'globalThis'
},
// Enable esbuild polyfill plugins
plugins: [
NodeGlobalsPolyfillPlugin({
buffer: true,
process: true,
}),
NodeModulesPolyfillPlugin()
]
}
},
build: {
rollupOptions: {
plugins: [
rollupNodePolyFill()
]
}
}
})
Be careful to use rollup-plugin-polyfill-node which is an updated and maintained fork of rollup-plugin-node-polyfills.

For me the above configuration did not work, I had to make changes in 3 files ,
in vite.config.ts , index.html and adding packages
1.Install Packages
yarn install process util buffer events
yarn add #esbuild-plugins/node-modules-polyfill
2.Update vite.config
import GlobalPolyFill from "#esbuild-plugins/node-globals-polyfill";
import react from "#vitejs/plugin-react";
import { resolve } from "path";
import { defineConfig } from "vite";
export default defineConfig({
plugins: [react()],
optimizeDeps: {
esbuildOptions: {
define: {
global: "globalThis",
},
plugins: [
GlobalPolyFill({
process: true,
buffer: true,
}),
],
},
},
resolve: {
alias: {
process: "process/browser",
stream: "stream-browserify",
zlib: "browserify-zlib",
util: "util",
},
},
});
3.Update index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/src/assets/images/favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite App</title>
<script>
window.global = window;
</script>
<script type="module">
import process from "process";
import EventEmitter from "events";
import {Buffer} from "buffer";
window.Buffer = Buffer;
window.process = process;
window.EventEmitter = EventEmitter;
</script>
</head>
<body>
<div id="root"></div>
<script type="module" src="./src/index.js"></script>
</body>
</html>

Another approach is:
npm i -D rollup-plugin-polyfill-node
Then update vite.config.ts with the following:
import nodePolyfills from 'rollup-plugin-polyfill-node'
rollupOptions: {
plugins: [
// ...plugins
nodePolyfills(),
],
// ...rollupOptions
},

Related

How to integrate react-native web to an existing react native project

We have a react-native project implemented using typescript, react-navigation, react-native-gesture-handler, redux/toolkit as the main packages
recently we integrated react-native-web into our project, but it is not running correctly.
there are several problems with our project:
we cannot load custom modules when we import them. for example:
import MyCustomComponent from './components/MyCustomComponent'
<View style={{flex: 1, backgroundColor: 'green'}}>
<MyCustomComponent/> <--- does not show up, event when it contains a simple View component, we will see a blank screen
</View>
but when I define MyCustomComponent inside the current file, it shows up with no problem:
function MyCustomComponent() {
return(
<View style={{flex:1, backgroundColor: 'yellow'}}></View>
)
}
export default function MyMainComponent() {
return (
<View style={{flex:1, backgroundColor: 'green'}}>
<MyCustomComponent/> <---- this shows up
</View>
)
}
anything that goes inside the redux Provider will not show up any more.
I think our webpack configuration is wrong, but since I'm not expert in web development, I need some help to figure out what's wrong. here is our webpack configuration:
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const appDirectory = path.resolve(__dirname);
const {presets} = require(`${appDirectory}/../babel.config.js`);
const compileNodeModules = [
// Add every react-native package that needs compiling
'react-native-gesture-handler',
'react-redux',
'react-native-reanimated',
'react-native-confirmation-code-field',
'react-native-calendars',
'#react-native-google-signin/google-signin',
'react-native-compressor',
'react-native-swipe-gestures',
'#react-native-async-storage',
'react-native-shared-element',
'#react-navigation',
'react-native-material-menu',
'#reduxjs/toolkit',
'react-navigation-shared-element',
'react-native-collapsible-tab-view',
'react-native-image-crop-picker',
'#react-native-community',
'react-nativbe-safe-area-context/lib',
'react-native-screens',
].map(moduleName =>
path.resolve(appDirectory, `../node_modules/${moduleName}`),
);
const babelLoaderConfiguration = {
test: /\.js$|tsx?$/,
// Add every directory that needs to be compiled by Babel during the build.
include: [
path.resolve(__dirname, '../index.web.js'), // Entry to your application
path.resolve(__dirname, '../src/index.web.tsx'), // Change this to your main App file
path.resolve(__dirname, '../src'),
...compileNodeModules,
],
use: {
loader: 'babel-loader',
options: {
cacheDirectory: true,
presets,
plugins: ['react-native-web'],
},
},
};
const svgLoaderConfiguration = {
test: /\.svg$/,
use: [
{
loader: '#svgr/webpack',
},
],
};
const tsLoaderConfiguration = {
test: /\.(ts|tsx|web.ts|web.tsx)?$/,
use: [
{
loader: 'ts-loader',
options: {
transpileOnly: true,
},
},
],
};
const imageLoaderConfiguration = {
test: /\.(gif|jpe?g|png)$/,
use: {
loader: 'url-loader',
options: {
name: '[name].[ext]',
esModule: false,
},
},
};
module.exports = {
entry: {
app: path.join(__dirname, '../index.web.js'),
},
output: {
path: path.resolve(appDirectory, 'dist'),
publicPath: '/',
filename: 'arcelor.bundle.js',
},
resolve: {
extensions: ['.web.tsx', '.web.ts', '.tsx', '.ts', '.web.js', '.js'],
alias: {
'react-native$': 'react-native-web',
},
},
module: {
rules: [
babelLoaderConfiguration,
imageLoaderConfiguration,
svgLoaderConfiguration,
tsLoaderConfiguration,
],
},
plugins: [
new HtmlWebpackPlugin({
template: path.join(__dirname, './index.html'),
filename: 'index.html',
inject: 'body',
}),
new webpack.HotModuleReplacementPlugin(),
new webpack.DefinePlugin({
// See: https://github.com/necolas/react-native-web/issues/349
// __DEV__: JSON.stringify(true),
__DEV__: process.env.NODE_ENV !== 'production',
process: {env: {}},
}),
],
};
I'm using webpack#^5.65.0
could anyone help me figure out what is the problem and how can I make react-native-web work with our project? thanks
getting Webpack up and running from scratch is not an easy task. I suggest you start with a ready to use an approach like cra or expo. then work your way up to customization.
Create-React-App
firstly, install the dependencies:
yarn add react-native-web react-scripts react-dom
create an HTML file in public/index.html and put the following content inside: gh:facebook/create-react-app/cra-template
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no"
/>
<title>Your App Title</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>
rename the index.js in project root to index.native.js. see
create a js file in src/index.js and put the following content inside:
import { AppRegistry } from "react-native";
import { App } from "./App";
AppRegistry.registerComponent(appName, () => App);
AppRegistry.runApplication("App", {
rootTag: document.getElementById("root"),
});
run the app by running react-scripts start
Customization
you may need to integrate preprocessors like react-native-reanimated/plugin to your babel config or edit your WebPack to add global variables like process.env. In order to do that you can either use react-scripts eject to have access to said configs or use tools like customize-cra.
Expo (Recommened)
In my opinion Expo is the best way to do it. Expo basically is create-react-app but for react-native that supports the react-native-web.
You can set up the expo for the web for your project by following the official guide.
install dependencies:
yarn add --global expo-cli
expo install react-native-web react-dom
yarn add expo
modify your root index.js to something like this:
import { registerRootComponent } from 'expo';
import App from './App';
registerRootComponent(App);
at this point you are ready to go. just rust expo start:web.
Customization
By running expo customize:web, you have access to Babel and Webpack config files.
Typescript basePath
If you are using "baseUrl": "src" in your tsconfig.json. you may need to set up the Babel too. because it may not necessarily follow your tsconfig.
// babel.config.js
module.exports = function (api) {
api.cache(true);
return {
presets: ['babel-preset-expo'],
plugins: [
'react-native-reanimated/plugin',
[
'module-resolver',
{
root: ['src'],
extensions: ['.tsx', 'json', '.ts', '.js'],
},
],
],
};
};

how to render javascript files at the end of body in reactjs+webpack?

I created a reactjs+ webpack SPA and tested it on 'Google pagespeed insights'. I have just one main.js file and it's getting rendered at the beginning.
here is the result
how do i resolve this ?
this is my webpack configuration :
const HtmlWebPackPlugin = require("html-webpack-plugin");
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
module.exports = {
optimization: {
minimizer: [new UglifyJsPlugin({
cache: true,
parallel: true,
// uglifyOptions: {
// compress: false,
// ecma: 6,
// mangle: true
// },
})]
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader?cacheDirectory=true"
}
},
{
test:/\.css$/,
use:['style-loader','css-loader']
},
{
test: /\.(ttf|eot|woff|woff2)$/,
use: {
loader: "file-loader",
},
},
{
test: /\.(png|jpg|svg)$/,
use: [{
loader: 'file-loader',
options: {
limit: 8000, // Convert images < 8kb to base64 strings
name: 'static/[name].[ext]'
}
}]
},
{
test: /\.html$/,
use: [
{
loader: "html-loader"
}
]
}
]
},
plugins: [
new HtmlWebPackPlugin({
template: "./src/index.html",
filename: "./index.html"
})
]
};
how could i tell webpack to load the js file at the end of the body ? or any other solution that helps to solve this issue?
and my index.html and index.js files are so simple.
index.html :
<!DOCTYPE html>
<html lang="fa">
<head>
<meta charset="utf-8">
<meta
name="viewport"
content="minimum-scale=1, initial-scale=1, width=device-width, shrink-to-fit=no"
/>
<link rel="shortcut icon" type="image/png" href="static/favicon.png"/>
<title>آسان یادبگیر</title>
</head>
<body dir="rtl">
<div id="mainDiv">
</div>
</body>
</html>
index.js :
import React from "react";
import ReactDOM from "react-dom";
import Theme from './styles/theme';
import { MuiThemeProvider} from '#material-ui/core/styles';
import CssBaseline from '#material-ui/core/CssBaseline';
import './styles/style.css';
import RTL from './jss-rtl';
import './static/favicon.png'
import App from './app';
ReactDOM.render(
<RTL>
<MuiThemeProvider theme={Theme}>
<React.Fragment>
<CssBaseline/>
<App/>
</React.Fragment>
</MuiThemeProvider>
</RTL>,
document.getElementById('mainDiv'));
here the google issue :
Eliminate render-blocking JavaScript and CSS in above-the-fold content: None of the above-the-fold content on your page could be rendered without waiting for the following resources to load. Try to defer or asynchronously load blocking resources, or inline the critical portions of those resources directly in the HTML.
Remove render-blocking JavaScript:
https://asanyadbegir.com/main.js
I added ' defer="true" ' to the dist/index.html file and it got better(50% better). then by using React-Loadable I splited my files. every thing is file now.

Reactjs: ReactTable css doesn't load css using import in js file

I am trying ReactTable using this link
Problem:
In my component when I try importing
import 'react-table/react-table.css'
css doesnt get import
When I inspect I see this as css url
blob:http://localhost:8080/cfd98537-05a8-4091-9345-d6ae877d3d25
but this works
<link rel="stylesheet" href="node_modules/react-table/react-table.css">
Files:
webpack.config.js
const HtmlWebPackPlugin = require("html-webpack-plugin");
const path = require("path");
const htmlWebpackPlugin = new HtmlWebPackPlugin({
template: "./src/index.html",
filename: "./index.html"
});
module.exports = {
entry: "./src/index.js",
output: {
path: path.resolve("dist"),
filename: "main.js"
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.css$/,
use: [
{
loader: "style-loader"
},
{
loader: "css-loader",
options: {
modules: true,
importLoaders: 1,
localIdentName: "[name]_[local]_[hash:base64]",
sourceMap: true,
minimize: true
}
}
]
}
]
},
plugins: [htmlWebpackPlugin]
};
index.js
import React from "react";
import ReactDOM from "react-dom";
import EmpTable from "./components/Emptable.js";
import "react-table/react-table.css";
function renderApp() {
ReactDOM.render(<EmpTable />, document.getElementById("root"));
}
renderApp();
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>React and Webpack4</title>
<link rel="stylesheet" href="node_modules/react-table/react-table.css">
</head>
<body>
<div id="root"></div>
</body>
</html>
Emptable.js
import React, { Component } from "react";
import ReactTable from "react-table";
import axios from "axios";
const column = [
{
Header: "User ID",
accessor: "userId"
},
{
Header: "ID",
accessor: "id"
},
{
Header: "Title",
accessor: "title"
},
{
Header: "Completed",
accessor: "completed"
}
];
class EmpTable extends Component {
constructor(props) {
console.log("Loading...");
super(props);
this.state = { value: [], isLoading: false };
this.loadData = this.loadData.bind(this);
}
componentDidMount() {
console.log("componentDidMount");
this.loadData();
}
componentDidCatch(error, info) {
console.log("componentDidCatch");
// You can also log the error to an error reporting service
console.log(error);
}
loadData() {
console.log("loadData");
axios
.get("https://jsonplaceholder.typicode.com/todos")
.then(response => {
this.setState({ value: response.data });
})
.catch(function(error) {
console.log(error);
});
}
render() {
return (
<div>
<button onClick={this.loadData}>Refresh Grid</button>
<ReactTable data={this.state.value} columns={column} />
</div>
);
}
}
export default EmpTable;
It looks like you're using CSS-Modules. Your WebPack module rule will generate a unique name for each CSS class when the document loads.
see this line in your config: localIdentName: "[name][local][hash:base64]"
When you include the react-table.css file in your project, css-modules will format the css names to keep them locally scoped, for example, the resulting mark-up: ( react__table___2zWw1) but react-table isn't using the locally scoped css names in it's code.
Your link to the stylesheet (link rel=...) should work, but if you're looking to use CSS-Modules, you must exclude the file from the modules loader, or exclude all of node_modules/react-table:
{
test: /\.css$/,
exclude: [/node_modules/],
...
}
You could try the above, or alternatively exclude specific .css files from using the module loader, based on their filename. In this case, you'd have to reference a custom react-table.customCSS.css file by copying it locally to your project and importing it again:
<code>
test: /\.customCSS.css$/,
use: [{
loader: 'style-loader',
}, {
loader: 'css-loader',
}],
},
</code>
Its working for me when i include
import 'react-table/react-table.css'
in main js file, where ever use react-table

best way to install react app manually

i am learning reactjs. And i install my react app by
create-react-app first
but i want to know is there any manual way to install react app
I will write the shortest tutorial :)
Step1: Create folder and file structure like below:
Step2: Install dependencies below:
npm install -S react react-dom prop-types
Step3: Install dev dependencies:
npm install -D babel-core babel-loader babel-plugin-transform-class-properties babel-preset-es2015 babel-preset-react html-webpack-plugin webpack
Step4: Add index.html file to root folder:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.3/css/bootstrap.min.css">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<!--Mounting point for React VDOM-->
<div id="root"></div>
</body>
</html>
Step5: Create webpack.config.js file in root folder with content:
let path = require('path'),
webpack = require('webpack'),
HtmlWebPackPlugin = require('html-webpack-plugin')
const PATHS = {
src: path.join(__dirname, 'src'),
dist: path.join(__dirname, 'dist'),
main: path.join(__dirname, 'src/main.js')
}
let wpConfig = {
entry: PATHS.main,
output: {
path: PATHS.dist,
filename: 'build.js',
},
module: {
loaders: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: {
"presets": [
"es2015",
"react"
],
"plugins": [
"transform-class-properties"
]
}
}
]
},
plugins: [
new HtmlWebPackPlugin({
title: 'My First React App',
template: './index.html'
})
]
}
module.exports = wpConfig
Step6: Add nmp command. In package.json file go to "scripts" sections and add build command like below:
"scripts": {
"build": "node_modules/.bin/webpack"
}
Step7: Create this simple React app file (main.js) in src folder:
import React from 'react'
import ReactDOM from 'react-dom'
const App = () => {
return (
<div>
<h1>Hello,</h1>
<p>This is my first react app!</p>
</div>
)
}
ReactDOM.render(
<App />,
document.getElementById('root')
)
Step8: Run command:
npm run build
Webpack will build and save files(build.js and index.html) to dist folder. Open your /dist/index.html file in browser and your first react app from zero is ready! Start with this basic app, then add some additional features like stylesheets (css, sass), router, webpack dev-server, hot reloading and etc.Happy coding!

ReactJs AdminLTE Dashboard

I am new in ReactJS. I want to use ReactJS-AdminLTE in my project. Can anybody tell how to use it with step by step process.
Steps I followed
1) I set Reactjs environment using https://www.tutorialspoint.com/reactjs/ tutorial
2) Then I install ReactJS-AdminLTE using command npm install adminlte-reactjs
My webpack.config file is
var path=require('path');
var config = {
entry: './main.js',
output: {
path: path.join(__dirname, "./"),
filename: 'index.js',
},
devServer: {
inline: true,
port: 8080
},
module: {
loaders: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: {
presets: ['es2015', 'react']
}
}
]
}
}
module.exports = config;
App.jsx
import React from 'react';
import reactjsAdminlte from 'adminlte-reactjs';
class App extends React.Component {
render() {
return (
<Box
width = 3
border = true
content = 'The body of the box'
theme = 'box-primary'
title = 'Collapsable'
collapsed = true
boxTools = ['collapse']
/>
);
}
}
export default App;
Index.html
<!DOCTYPE html>
<html lang = "en">
<head>
<meta charset = "UTF-8">
<title>React App</title>
</head>
<body>
<div id = "app"></div>
<script src = "index.js"></script>
</body>
</html>
But result is not displaing.
Are you using ReactDOM to render your app component to the HTML?
import ReactDOM from 'react-dom';
ReactDOM.render(
<App />,
document.getElementById('app')
);

Resources