3

I am using NextJS to build an SSR web app and currently have just two dummy pages, index and about. The site loads fine, except that NextJS throws up a bunch of JS files:

  1. https://www.schandillia.com/_next/341c66db-91d8-47da-97af/page/index.js
  2. https://www.schandillia.com/_next/341c66db-91d8-47da-97af/page/about.js

  3. https://www.schandillia.com/_next/341c66db-91d8-47da-97af/page/_app.js

  4. https://www.schandillia.com/_next/341c66db-91d8-47da-97af/page/_error.js

  5. https://www.schandillia.com/_next/static/commons/main-975e462d96245579782f.js

Since these are created and get injected into the DOM during compile-time, it results in several round trips during page-load and I'd love to avoid that. Is there any way to concatenate them all into a single JS payload during compile and then inject that concatenated bundle into the DOM using some kind of Webpack middleware? My next.config.js currently looks like this:

const path = require('path');
const glob = require('glob');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const webpack = require('webpack');
require('dotenv').config();

module.exports = {
  distDir: '.build',
  webpack: (config) => {
    config.module.rules.push(
      {
        test: /\.(css|scss)$/,
        loader: 'emit-file-loader',
        options: {
          name: path.join('dist', '[path][name].[ext]'),
        },
      },
      {
        test: /\.(css|sass|scss)$/,
        use: ExtractTextPlugin.extract([
          {
            loader: 'css-loader',
            options: {
              sourceMap: false,
              minimize: true,
            },
          },
          'postcss-loader',
          {
            loader: 'sass-loader',
            options: {
              includePaths: ['styles', 'node_modules']
                .map(d => path.join(__dirname, d))
                .map(g => glob.sync(g))
                .reduce((a, c) => a.concat(c), []),
            },
          },
        ]),
      },
      {
        test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
        loader: 'url-loader?limit=10000&mimetype=application/font-woff&outputPath=static/',
      },
      {
        test: /\.(svg|ttf|eot)$/i,
        loader: 'file-loader?outputPath=static/',
        options: {
          name: '[path][name].[ext]',
        }
      },
      {
        test: /\.(png|jpe?g|gif)$/i,
        loaders: [
          'file-loader?outputPath=static/',
          'image-webpack-loader?bypassOnDebug&optimizationLevel=7&interlaced=false',
        ],
      },
    );
    config.plugins.push(
      new ExtractTextPlugin({
        filename: path.join('static', `${process.env.CSS}.min.css`),
      }),
      new webpack.DefinePlugin({
        'process.env.CSS': JSON.stringify(process.env.CSS),
        'process.env.NAVBAR_LOGO': JSON.stringify(process.env.NAVBAR_LOGO),
      }),
    );
    return config;
  },
};

Any tips?

2
  • try use dynamic import, it worked once for me Commented Sep 4, 2018 at 13:04
  • The scripts I've mentioned are generated BY NextJS. These aren't my imports. Of course, all imports are dynamic. Commented Sep 4, 2018 at 18:02

1 Answer 1

3

Your index and about pages are loaded because you are pre-fetching your links.

    <Link prefetch href="/">
      <a>Home</a>
    </Link>
    <Link prefetch href="/about">
      <a>About</a>
    </Link>

What you do when you are pre-fetching a Link in NextJS is that you tell the browser to fetch the JS code for the page behind the link before the user clicks on it. Do not set the prefetch prop if you don't want this behaviour.

    <Link href="/">
      <a>Home</a>
    </Link>
    <Link href="/about">
      <a>About</a>
    </Link>

The other bundles are just how NextJS works and as far as I know it is hardcoded (source) but I could be wrong.

Sign up to request clarification or add additional context in comments.

3 Comments

I understand the bundles are being fetched due to the prefetch directive, but I do need the functionality. What I need is for all those individual files (the one being loaded initially AND the ones being loaded due to the prefetch directive) to be merged into a single JS file before being served to the browser upon page load. Is that possible? Or desirable?
Ok I get it, it may not be desirable in most cases, due to the fact that pages access pattern is unique to each page and you only want to load the js that is likely to be executed. There is some experimental projects that, based on google analytics data will trigger the prefetch of some resources (github.com/addyosmani/predictive-fetching) but I don't know if it's prod ready yet. The fact that the 2 pages are not bundled together is balanced by http multiplexing and browser cache, which makes large bundles less efficient than smaller bundles
Ahh, got it. I did suspect it might grow inefficient as more pages are added. Thanks for confirming. Am accepting your answer though.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.