Create a react "development" build - reactjs

What's the best way to create a development build bundle for a create-react-app project?
npm run build builds something that's buggy in ways that development isn't and it ignores my NODE_ENV setting

This works for the react-scripts 5.0.1:
Install react-app-rewired: npm install react-app-rewired
Replace the build script in your package.json:
"scripts": {
"build": "react-app-rewired build"
}
Create the config-overrides.js file in the root folder of your project.
module.exports = function override(config) {
config.mode = 'development';
config.optimization.minimize = false;
return config;
};
If you want to create two build modes you can add a condition that checks the mode.
"scripts": {
"build": "cross-env react-app-rewired build",
"build:dev": "cross-env DEV_MODE=true react-app-rewired build",
}
module.exports = function override(config) {
if (process.env.DEV_MODE) {
config.mode = 'development';
config.optimization.minimize = false;
}
return config;
};

Related

How Can I Configure Storybook to Use React-App-Rewired?

I'm working on a project that implements react-app-rewired to send headers to the server in order to bypass ReferenceError: SharedArrayBuffer is not defined (I'm getting this error from using the #ffmpeg/ffmpeg library).
// config-overrides.js
const {
override,
// disableEsLint,
// addBabelPlugins,
// overrideDevServer
} = require('customize-cra')
module.exports = {
devServer(configFunction) {
// eslint-disable-next-line func-names
return function (proxy, allowedHost) {
const config = configFunction(proxy, allowedHost)
// Set loose allow origin header to prevent CORS issues
config.headers = {
'Access-Control-Allow-Origin': '*',
'Cross-Origin-Opener-Policy': 'same-origin',
'Cross-Origin-Embedder-Policy': 'require-corp',
'Cross-Origin-Resource-Policy': 'cross-origin'
}
return config
}
}
}
// package.json
"scripts": {
"start": "react-app-rewired start",
"build": "react-app-rewired build",
"test": "react-app-rewired test --transformIgnorePatterns \"node_modules/(?!siriwave)/\"",
"eject": "react-scripts eject",
"storybook": "start-storybook -p 6006 -s public",
"build-storybook": "build-storybook -s public"
}
Though this works when I run npm start, meaning the headers get sent to the server, it doesn't work when I run npm run storybook, and I still get the SharedArrayBuffer is not defined error. I'm assuming it's because npm run storybook still uses react-scripts as opposed to react-app-rewired under the hood, but I'm not sure where I can change the configurations for this. Any ideas?
You can add a custom webpack configuration in storybook/main.js like so:
https://storybook.js.org/docs/react/builders/webpack
So you can use the same webpack modification as you did with react-app-rewired

Can't resolve 'crypto' in react-oauth2-pkce

I have a React.js application which is part of an oAuth2 architecture and in order to get a token it uses Authorization Code + PKCE flow as explained here.
The issue is that when I try to run the app npm start I get the following error:
I tried with the suggested approach at many places to add the following in my package.json after devDependencies:
"browser": {
"crypto": false
}
but I still have the same issue. I am using Node.js 14.0.0
This is a big issue, and I will not elaborate on the various moving parts that causes the issue.
What you need to do:
run yarn add crypto-browserify stream-browserify buffer
run yarn add -D react-app-rewired
create a new file in the root of your directory: config-overrides.js with the contents:
const webpack = require('webpack');
module.exports = function override(config, env) {
config.resolve = config.resolve || {};
config.resolve.fallback = config.resolve.fallback || {};
config.resolve.fallback.crypto = require.resolve('crypto-browserify');
config.resolve.fallback.stream = require.resolve('stream-browserify');
config.resolve.fallback.buffer = require.resolve("buffer")
config.resolve.alias.buffer = 'buffer'
config.plugins = config.plugins || [];
config.plugins.push(new webpack.ProvidePlugin({Buffer: ['buffer', 'Buffer'],}));
return config;
}
Edit your package.json and make sure it looks like this:
...
"scripts": {
"start": "react-app-rewired start",
"build": "react-app-rewired build",
"test": "react-app-rewired test",
"eject": "react-scripts eject"
},
...
run rm -fr node_modules/.cache
Read more:
The actual issue that caused all this - "BREAKING CHANGE: webpack < 5 used to include polyfills..." - issue 11756 at CRA
related react-oauth2-pkce issue 33
How to re-wire CRA

Framer motion error after install the package and import

I get this error after installing and importing framer-motion in the middle of my project
Can't import the named export 'Children' from non EcmaScript module (only default export is available)
I have tried to install after npx create-react-app and it works fine. This only happened if I install the package in the middle. This is my project
First, install the react-app-rewired NPM package as a dev dependency.
Then, in package.json, update the start, build, and test scripts to replace react-scripts with react-app-rewired:
"scripts": {
"start": "react-app-rewired start",
"build": "react-app-rewired build",
"test": "react-app-rewired test",
"eject": "react-scripts eject"
},
Finally, paste this into a file in the project root directory named config-overrides.js:
module.exports = function override(webpackConfig) {
webpackConfig.module.rules.push({
test: /\.mjs$/,
include: /node_modules/,
type: "javascript/auto"
});
return webpackConfig;
}
Now npm start / yarn start should work.

Local development of multiple react apps in a single folder

Right now there're 3 separate React apps created with create-react-app. I need to put them into one folder. It works fine when I do npm run build. The question is how can I configure webpack to be able to run local dev server for a specific app with a command like npm run dev:second-app
To configure webpack without ejecting I use react-app-rewired package. Here's the code:
config-overrides.js
const path = require('path');
module.exports = function override(config, env) {
config.entry = {
firstApp: "./src/firstApp/index.js",
secondApp: "./src/secondApp/index.js",
thirdApp: "./src/thirdApp/index.js"
}
config.optimization.runtimeChunk = false;
config.optimization.splitChunks.name = 'shared';
config.output = {
path: path.resolve(__dirname, 'shopify'),
publicPath: '/',
filename: 'assets/[name].main.js',
chunkFilename: 'assets/[name].chunk.js'
}
return config;
};
package.json
...
"scripts": {
"start": "react-app-rewired start",
"build": "react-app-rewired build",
"postinstall": "patch-package"
}
...

How do I change `src` folder to something else in create-react-app

I'd like to know if it's possible using react-script to rename src to something else like app folder
You can use react-app-rewired to override react paths configuration.
In my case, I can change the paths in config-overrides.js file
const path = require('path');
module.exports = {
paths: function (paths, env) {
paths.appIndexJs = path.resolve(__dirname, 'mysrc/client.js');
paths.appSrc = path.resolve(__dirname, 'mysrc');
return paths;
},
}
Not sure if this answers your question but I'll give it a shot. My directory structure looks like this:
/root
--/app
----/build
----/public
------index.html
----/src
------index.js
app.js
package.js
My /root/package.json has this in it:
"scripts": {
"build": "cd app && npm run build",
"start": "node app.js",
"serve": "cd app && npm run start"
},
"dependencies": {
"express": "^4.8.0",
"react": "^16.2.0",
"react-dom": "^16.2.0",
"react-router": "^4.2.0",
"react-router-dom": "^4.2.2",
"react-scripts": "^1.0.17"
},
and my /root/app/package.json looks like this:
"scripts": {
"build": "react-scripts build",
"start": "set PORT=3000 && react-scripts start"
},
"dependencies": {
"react-scripts": "^1.0.17"
}
To run the development version of Reactjs, in the /root I can just npm run serve to serve up the dev version.
I am using node and express, so to run the production version of Reactjs,
in the /root I can just npm run build to create the /root/app/build directory. I have a router that looks like this:
var options = {root : config.siteRoot + '/app/build'};
mainRte.all('/', function(req, res) {
console.log('In mainRte.all Root');
res.sendFile('index.html', options);
});
so when I run /root/app.js in node and surf to "/" it opens up /root/app/public/index.html and then /root/app/index.js.
Hopefully that helps.
react-app-rewired allows for this exact customization.
1
Install react-app-rewired as a dev dependency:
npm install --save-dev react-app-rewired
2
In package.json, change these lines
"scripts": {
"react-start": "react-scripts start",
"react-build": "react-scripts build",
"react-test": "react-scripts test",
...
}
to
"scripts": {
"react-start": "react-app-rewired start",
"react-build": "react-app-rewired build",
"react-test": "react-app-rewired test",
...
}
3
Create a config-overrides.json file in your project directory root with the following contents:
const paths = require('react-scripts/config/paths')
const path = require('path')
// Make the "app" folder be treated as the "src" folder
paths.appSrc = path.resolve(__dirname, 'app')
// Tell the app that "src/index.js" has moved to "app/index.js"
paths.appIndexJs = path.resolve(__dirname, 'app/index.js')
Now your app folder is the new src!
You can also customize many other things, such as the name of the "public" folder:
paths.appPublic = path.resolve(__dirname, 'subfolder/public')
paths.appHtml = path.resolve(__dirname, 'subfolder/public/index.html')
And you can also change the location of package.json and node_modules. See here for the full list.
I know this is an old question but I'm still gonna post my solution since it might help someone.
I got it working by doing the following:
Run npm run eject. This exposes some internal configuration stuff from create-react-app
Open your package.json and edit the respective regexes under jest.collectCoverageFrom and jest.testMatch to match your test path
Alter the paths for appSrc, appIndexJs and testsSetup in the config/paths.js file
T0astBread's answer is nearly perfect, but there's an additional reference to "src" that he missed inside modules.js.
Specifically:
return {
src: paths.appSrc,
};
needs to be changed to
return {
newSrcName: paths.appSrc,
};
This is a great question and a valid scenario for changing this folder name is when migrating old react projects to CRA.
Here's another approach I found that breaks less things:
Create a symlink with:
ls -s ./app src
Then add this in config-overrides.js, to allow webpack to process the symlink:
module.exports = (config, ...rest) => {
return { ...config, resolve: { ...config.resolve, symlinks: false } };
};
Then install react-app-rewired and add this to your package.json:
"start": "react-app-rewired start",
While Cong Dan Luong's answer is correct as far as renaming the folder goes, it will break testing with jest. You need to expand the config-overrides.js module.exports part with the following:
module.exports = {
jest: function(config) {
config.collectCoverageFrom = ['client/**/*.{js,jsx,ts,tsx}', '!client/**/*.d.ts'];
config.testMatch = [
'<rootDir>/client/**/__tests__/**/*.{js,jsx,ts,tsx}',
'<rootDir>/client/**/*.{spec,test}.{js,jsx,ts,tsx}',
];
config.roots = ['<rootDir>/client'];
return config;
},
// The paths config
paths: function(paths, env) {
paths.appIndexJs = path.resolve(__dirname, 'client/index.js');
paths.appSrc = path.resolve(__dirname, 'client');
return paths;
},
};
In my above example I am using 'client' instead of 'src'. npm test now works.
Perhaps a symbolic link might address your reasons for wanting to do this:
ln -s ./src/ ./app
The src folder will remain but you can work with it as if it was the app folder.
If, like me you're using vscode you can also do:
Cmd-shift-p search workspace settings, and add the following:
{
"files.exclude": {
"src/": true
}
}
You could do similarly with other editors
Create file in root of your project, insert this code and run.
const fs = require('fs');
const path = './node_modules/react-scripts/config/paths.js';
const folder = 'app';
fs.readFile(path, 'utf8', (err, data) => {
if (err) throw err;
data = data.replace(/src/g, folder);
fs.writeFile(path, data, 'utf8');
});

Resources