Bundle and Distribute Next.js Sites via NPM

engineering grouparoo next.js node.js 
2021-06-03 - Originally posted at https://www.grouparoo.com/blog/distributing-nextjs-via-npm
↞ See all posts


Next.js and NPM

Grouparoo uses Next.js to build our web frontend(s), and we distribute these frontend User Interfaces (UIs) via NPM as packages, e.g. @grouparoo/ui-community. This allows Grouparoo users to choose which UI they want to use (or none) by changing their package.json:

Example package.json for a Grouparoo project:

1{ 2 "author": "Your Name <email@example.com>", 3 "name": "grouparoo-application", 4 "description": "A Grouparoo Deployment", 5 "version": "0.0.1", 6 "dependencies": { 7 "@grouparoo/core": "0.3.3", 8 "@grouparoo/postgres": "0.3.3", 9 "@grouparoo/mailchimp": "0.3.3", 10 "@grouparoo/ui-community": "0.3.3" // <-- Choose UI Package to install 11 }, 12 "scripts": { 13 "start": "cd node_modules/@grouparoo/core && ./bin/start" 14 }, 15 "grouparoo": { 16 "plugins": [ 17 "@grouparoo/postgres", 18 "@grouparoo/mailchimp", 19 "@grouparoo/ui-community" // <-- Choose UI Package to load 20 ] 21 } 22}

Here is how we bundle up our Next.js applications so that our customers can use them out of the box.

next build and npm run prepare

The first step in “compiling” your Next.js projects is to use the next build command. We alias this to the “prepare” npm lifecyle command so that this command will be run automatically before npm publish. In this way we can ensure that we always have a freshly built bundle to use when we publish our packages.

This is different from Next’s recommendation to alias next build to npm build because we are not “deploying” our sites - we are publishing them. Many hosting providers look for a build script in your pacakge.json to run when the deploy, hence Next.js’ recommendation.

.npmignore vs .gitignore

The next step in bundling up a Next.js application for deployment via NPM is to include the build files. In all Next.js projects, you want to ignore the .next folder in your .gitignore. The .next folder is where Next.js keeps all the build artifacts it creates — minified javascript, css chunks, etc. Assuming your “source code” is Typescript and SCSS, everything in the .next folder should be ignored, and rebuilt as needed from the source.

BUT… the content of .next is actually what the visitors to your site really load - that’s the HTML, CSS, and Javascript that ends up in the browser. Since we are trying to package up a usable site, we need to bundle the contents of .next into our NPM bundles. However, we still want to exclude these rapidly changing files from git’s history.

The solution is a .npmignore file! By default, NPM will use a .gitignore file to determine which files it packs up into your packages, and which files it ignores. But, you can override this behavior by placing a .npmignore in your project. For example:

.gitignore

.DS_Store
node_modules
.next

.npmignore

.DS_Store
node_modules
# .next is included

Skip the .pack files

The final thing we learned is that while the contents of the .next directory are needed for your visitors, not everything is needed. We saw that we were shipping 300mb packages to NPM for our Next.js UIs. We dug into the .next folder and learned that if you opt-into Webpack v5 for your Next.js site, large .next/cache/*.pack files will be created to speed up how Webpack works. This is normal behavior, but we were inadvertently publishing these large files to NPM! We added the .next/cache/* directory to our .npmignore and our build sizes went down to a more reasonable 20mb.

Our final .npmignore looks like this:

.npmignore

.DS_Store
node_modules
.next/cache/*
Hi, I'm Evan

I write about Technology, Software, and Startups. I use my Product Management, Software Engineering, and Leadership skills to build teams that create world-class digital products.

Get in touch