8

I try to lazy load routes using react-router-dom but it doesn't work. Webpack should automatically split chunks on import() but it doesn't, I always end up with one main.hash.js file instead of multiple chunks. Is there something I'm missing ?

App Component:

import * as React from 'react';
import { Route, BrowserRouter, Link } from 'react-router-dom';
const Todos = React.lazy(() => import('routes/Todos'))

class App extends React.Component<{}, {}> {
  render() {
    return (
      <>
        <BrowserRouter>
          <React.Suspense fallback={<div>loading...</div>}>
            <Route exact path="/" render={() => <Link to="/todos">Todos</Link>} />
            <Route exact path="/todos" component={Todos} />
          </React.Suspense>
        </BrowserRouter>
      </>
    )
  }
}
export default App;

Here is the webpack config in case it may be related to some plugins or missing config on this side:

webpack common config:

const webpack = require('webpack');

const HtmlWebPackPlugin = require('html-webpack-plugin');
// clean folder (dist in this case)
const CleanWebpackPlugin = require('clean-webpack-plugin');
// copy files
const CopyPlugin = require('copy-webpack-plugin');

const path = require('path');

module.exports = {
  entry: path.resolve(__dirname, 'src', 'index.tsx'),
  resolve: {
    extensions: ['.js', '.ts', '.tsx', '.scss'],
    alias: {
      'src': path.resolve(__dirname, 'src/'),
      'components': path.resolve(__dirname, 'src/components/'),
      'routes': path.resolve(__dirname, 'src/routes/'),
    }
  },
  plugins: [
    new CleanWebpackPlugin(['dist'], {}),
    new HtmlWebPackPlugin({
      template: "./src/index.html",
      filename: "index.html"
    }),
    new CopyPlugin([
      { from: 'assets', to: 'assets' },
    ]),
  ]
};

webpack prod config:

const merge = require('webpack-merge');
const common = require('./webpack.common.js');
const path = require('path');

// split css per js file
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
// optimize js
const TerserPlugin = require('terser-webpack-plugin');
// optimize css
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
// service-worker
const Workbox = require('workbox-webpack-plugin');

module.exports = merge(common, {
  mode: 'production',
  module: {
    rules: [
      {
        test: /\.ts|\.tsx$/,
        loader: "ts-loader",
        include: path.resolve(__dirname, 'src')
      },
      {
        test: /\.scss$/,
        loader: MiniCssExtractPlugin.loader
      },
      {
        test: /\.scss$/,
        loader: 'css-loader',
        options: {
          modules: true,
          localIdentName: '[hash:base64:5]'
        }
      },
      {
        test: /\.scss$/,
        loader: 'postcss-loader',
      },
      {
        test: /\.scss$/,
        loader: 'sass-loader',
      }
    ],
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: '[name].[hash].css',
      chunkFilename: '[id].[hash].css',
    }),
    new OptimizeCssAssetsPlugin({}),
    new Workbox.GenerateSW({
      clientsClaim: true,
      skipWaiting: true,
      exclude: [/\.(?:png|jpg|jpeg|svg)$/],
      runtimeCaching: [
        {
          urlPattern: /https?:\/\/.+/,
          handler: 'StaleWhileRevalidate',
          options: {
            cacheableResponse: {
              statuses: [0, 200]
            }
          }
        }, {
          urlPattern: /\.(?:png|jpg|jpeg|svg)$/,
          handler: 'CacheFirst',
        }],
    })
  ],
  optimization: {
    minimizer: [new TerserPlugin()],
  },
  output: {
    filename: '[name].[contenthash].js',
    chunkFilename: '[name].[contenthash].js',
    path: path.resolve(__dirname, 'dist')
  }
});

1 Answer 1

10

From: https://github.com/webpack/webpack/issues/5703#issuecomment-357512412

compilerOptions.module has to be set to esnext in order for webpack to split dynamic imports.

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

Comments

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.