How to analyze Next Js bundle size and content - reactjs

I've just upgrated to Next JS 9.0 and when I run a build there's a fantastic new feature which shows you the size of all the compiled pages. They're all around 20-30k except for pages which use Formik which tend to be at least double that size. The main problem is that the app.js file is over 600k and red.
Is there a way to dive further and see on a more granular level what's making up all my bundles?

Install #next/bundle-analyzer and cross-env as dev dependency:
yarn add -D #next/bundle-analyzer cross-env
Create a next.config.js file in the root of your project directory (next to package.json) and paste the code below:
const withBundleAnalyzer = require('#next/bundle-analyzer')({
enabled: process.env.ANALYZE === 'true',
})
module.exports = withBundleAnalyzer({
reactStrictMode: true,
})
Go to your package.json file and add the line below to the scripts section:
"analyze": "cross-env ANALYZE=true next build"
Now you can run yarn analyze or npm run analyze to analyze your bundle size.

You can use below package to analyze main bundle:
https://github.com/vercel/next.js/tree/canary/packages/next-bundle-analyzer

Related

Where does React put the continuous build files when using create-react-app

I'm using create-react-app. When I run npm start (react-scripts start) it continuously builds the changes for me and does it magic. But what is the output folder for that? I know when I build it manually where the files go.
I want to use firebase emulator to serve the current version (the continuous build) of my react all but I don't understand where's the output folder or how to achieve it.
You could try this package https://github.com/Nargonath/cra-build-watch
Install it and add the script to your package.json
{
"scripts": {
"watch": "cra-build-watch"
}
}
and run it
npm run watch
more info here
https://ibraheem.ca/writings/cra-write-to-disk-in-dev/
and if you go to the react repo issue linked in the article you would find more workarounds
tl;dr
run npm run build, not npm run start
More Detail
react-scripts start runs webpack-dev-server internally. As a default setting, webpack-dev-server serves bundled files from memory and does not write files in directory.
If you want to write files with webpack-dev-sever, you could set writeToDisk option to true in your dev server configuration.
However, I dont think this is what you want to serve on firebase emulator. Webpack-dev-server does not build optimal app for production, and you also need to use react-app-rewired to customize dev server configuration in cra template.
What you want to do is npm run build to run react-scripts build, which builds optimized production app in /build directory.

Craco build fails, taking aliased folder as external package

I'm using craco and craco-alias to implement aliases for imports in my Create React App project.
Followed instructions in https://github.com/gsoft-inc/craco/blob/master/packages/craco/README.md#installation and https://github.com/risenforces/craco-alias#readme
I configured package.json to use craco instead of react-scripts for starting dev server, tests and production build
...
"scripts": {
"start": "craco start",
"build": "craco build",
"test": "craco test",
"lint:css": "stylelint './src/**/*.css'",
"lint:js": "eslint 'src/**/*.js'",
"test:w": "craco test --watch",
"postinstall": "patch-package"
},
...
Then I created jsconfig.json file w aliases paths
"compilerOptions": {
"baseUrl": "./src",
"paths": {
"#components": ["components/*", "components"],
"#constants": ["constants/*", "constants"],
"#assets": ["assets/*", "assets"],
"#store": ["store/*", "store"],
"#utils": ["utils/*", "utils"]
},
"include": ["src"],
"exclude": ["node_modules", "build", "coverage"]
}
And craco.config.js file, which uses craco-alias plugin
/* craco.config.js */
const CracoAlias = require('craco-alias');
module.exports = {
plugins: [
{
plugin: CracoAlias,
options: {
baseUrl: './src',
source: 'jsconfig',
}
}
]
}
Now I'm using aliases for imports in my app like this
// root index.js file
...
import Layout from '#components/Layout';
import store from '#store'; // this line causes error on CI build
function App() {
return (
<Layout>
/* inner components */
</Layout>
);
}
Everything works fine (aliased imports works on dev-server, in jest tests and even if I serve locally built project) until I push it to github repo. That repo has configured github actions to build and test project on remote server and it fails with error on build step, after installing all packages.
Run yarn build
yarn run v1.22.4
$ craco build
Creating an optimized production build...
Browserslist: caniuse-lite is outdated. Please run next command `npm update`
Failed to compile.
./src/index.js
Cannot find module: '#store'. Make sure this package is installed.
You can install this package by running: npm install #store.
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
##[error]Process completed with exit code 1.
Could somebody help me understand what wrong with my code? Why craco or webpack expect '#store' to be external package instead of aliased import of internal module?
In my case problem wasn't in craco or webpack, but in my previous actions and OS filesystem differences. I'm using Windows 10 and WSL in VS Code terminal. So before I use '#' symbol for aliases I tried to use CamelCase for my folders and renamed it via windows explorer (because for me it was simpler to close VSCode and rename files via explorer than to open new bash terminal in new VSCode window after closing opened files).
Then I prefer to use '#' symbol and rename folders back to lowercase. I configured aliases and pushed changes to remote github repo, where CI actions were run. When CI was running actions it can't find 'store' folder (because previously I renamed it to 'Store' and it was last saved path to folder in git), so it tried to find external package named 'store'.
To fix this I change git config to stop ignoring namecasing for my folder by running command git config core.ignorecase false. Git history was updated, I push it to remote repo and CI actions succeeded.

How can I deploy my react project for production?

How can transform my react project into script to connect it to html page?
I am a new one in react please be tolerant. My boss demands to get completed script to connect it to html page without node and etc. What shall I do? Thank you.
Please check this url:
https://blog.bitsrc.io/react-production-deployment-part-3-heroku-316319744885
Also, Please check these steps:
In package.json, added this line to the scripts
"heroku-postbuild":
"NPM_CONFIG_PRODUCTION=false npm install --prefix client && npm run
build --prefix client".
Then added this
"engines": { "node" : "[your node version]" } after scripts.
In index.js, put the following code after your routes set up
if (process.env.NODE_ENV === "production") {
app.use(express.static("client/build"));
const path = require("path");
app.get("*", (req, res) => {
res.sendFile(path.resolve(__dirname, "client", "build",
"index.html"));
});
}
I assume that you use git for version control and already install Heroku.
Open your terminal, then Heroku login -> Heroku create -> git push Heroku
master. If you do not get any error, you are a success to deploy your app.
Hope you will get it to work.
In order to get rid of node, you need to first build your project. If you've initialized your project with create-react-app, run this command:
npm run build
A folder named 'build' will appear in your project root containing your production app. Now the build folder is ready to build and you can serve it with a static server like 'serve'. To install 'serve' via npm, do this:
npm install -g serve
that's it! you can serve it now:
serve -s build
You can find out more about deployment here:
https://github.com/facebook/create-react-app/blob/master/packages/react-scripts/template/README.md#deployment
by using create-react-app
https://create-react-app.dev/docs/getting-started
https://create-react-app.dev/docs/deployment
dev: npm start or yarn start.
prod: npm run build or yarn build.

Create react app, reload not working

I just started coding in React using create-react-app. In the documentation it's said
The page will reload if you make edits.
I don't know which module is responsible for auto reload (webpack or react-hot-reloader?) but it's not working. I edited file using different editors (Sublime, VIM, ..) but it seems problem is for something else. Any advice how to debug it?
After too many searches I found Webpack watch uses inotify to observe file changes and in ubuntu it's set to a low value. a quick fix:
sudo -i
echo 1048576 > /proc/sys/fs/inotify/max_user_watches
exit
If you want change it permanently (from Ronald answer):
echo "fs.inotify.max_user_watches=524288" >> /etc/sysctl.conf
sudo sysctl -p
You may also need to add a .env file in the root directory of your project with this line "FAST_REFRESH=false" as noted in create react app docs.
echo "FAST_REFRESH=false\n" | cat > .env
Year 2021
I had this issue in react ^17.0.2 I fixed it by adding a .env file and setting FAST_REFRESH=false.
Just create a .env file in the root directory of your project and add FAST_REFRESH=false in the file.
For Ubuntu users, run this in the terminal:
sudo gedit /etc/sysctl.conf
Scroll to the bottom and paste:
fs.inotify.max_user_watches=524288
Save and close the editor, then run this:
sudo sysctl -p
To check your success:
cat /proc/sys/fs/inotify/max_user_watches
This should return 524288
by apsrcreatix
Ref: https://github.com/flathub/com.visualstudio.code/issues/29#issuecomment-477126012
I had the same problem in Ubuntu.
The problem was resolved by deleting node_modules and then run
yarn install // or npm install
I hope to save someone else the same pain I experienced.
I'm using Windows 10 and Ubuntu 20.04 WSL, with nvm to manage node/npm.
I had to:
Use Node v16.14.2 in nvm (which also uses npm 8.5.0)
Change react-scripts from "react-scripts": "5.0.0" to "react-scripts": "4.0.3" in my package.json file
Change my package.json start script to
"start": "CHOKIDAR_USEPOLLING=true react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
I then ran npm install to update react scripts and restarted the bash terminal
I also followed Ronald Araújo's advice in his answer for good measure.
5 hours later, it's finally working!
Good luck everyone!
There actually is solution to get Fast refresh working.
Use this patch https://github.com/facebook/create-react-app/pull/11105/files
From #pmmmwh
Use https://www.npmjs.com/package/patch-package for editing your dependencies.
install patch-package (via npm or yarn into your project)
npm: npm i patch-package
yarn: yarn add patch-package postinstall-postinstall
Edit package.json and add postinstall script
"scripts": {
+ "postinstall": "patch-package"
}
Edit file YOUR_PROJECT/node_modules/react-dev-utils/webpackHotDevClient.js - with changes introduced in github pull request above
run npx patch-package react-dev-utils
commit changes created by this script (e.q. ./patches/react-dev-utils+11.0.4.patch)
run your app, now it will refresh on changes
Or wait for new release of react-dev-utils (it is not yet released, last version #11.0.3 doesn't contain this update).
My hot reload in Create React app broke due to updating some packages (probably because of typescript). I had to solve it without the ejecting of CRA.
I managed to fix it by upgrading to version 16.10 of these packages:
"react": "^16.10.0",
"react-dom": "^16.10.0"
And it worked just fine!
My code in index.tsx:
...
const isDev = process.env.NODE_ENV === 'development'
const rootEl = document.getElementById('root')
ReactDOM.render(<App />, rootEl)
if (isDev && module.hot) {
module.hot.accept('screens/App', () => {
ReactDOM.render(<App />, rootEl)
})
}
Hint:
First try just this code (maybe you are setting wrong path)
if (module.hot) {
module.hot.accept()
}
If this start working then you want to specify the path in order to make hot loading more effective (less bubbling = shorter loading)
Try adding CHOKIDAR_USEPOLLING=true in a .env file.
If the React webpage is not reloading upon saving changes, try adding this line to the App.js file:
import React from 'react';
After create-react-app,I change my project's name.This is one of reasons which make reload not working.Then I create-react-app again,reload is working now.

Preact and Webpack for Production

Just trying to make sure I am setting up my preact js correct for production.
In my webpack setup with preact, and run npm run build I notice with Bundle Analyzer Plugin the path for the preact js file is
/node_modules/preact/dist/preact.js and not
/node_modules/preact/dist/preact.min.js
I have uglify and minify js set up as well, but just thought it was curious that the minified package is not picked up ?
Entry script within webpack
entry: { app: './src/index.js', vendor: [ 'preact', 'preact-router' ] },
Npm Run build script
"build": "cross-env NODE_ENV=production webpack --progress -p --display-modules --display-chunks"
The default main for preact is dist/preact.js - preact.min.js is there for people who want to take advantage of minification when not applying their own (people hotlinking it off a CDN, for example), and to measure real-world output size.
You're already applying UglifyJS to your bundle by running webpack with the -p flag, so you needn't worry too much about trying to use dist/preact.min.js. It could save a few bytes, but nothing major. The file you're using (dist/preact.js) is actually already run through UglifyJS by Preact, it's just not compressed but not mangled (so the variable names remain intact).

Resources