How to get dynamic imports to work in webpack 4

Coco picture Coco · Jun 21, 2018 · Viewed 9.3k times · Source

I'm trying to migrate my app to webpack 4. My head hurts already.

Dynamic imports - this is my method of code splitting (page by page). But I can't get it to work. Have set up very simple tester with following packages:

"devDependencies": {
    "babel-core": "^6.26.3",
    "babel-loader": "^7.1.4",
    "babel-plugin-transform-async-to-generator": "^6.24.1",
    "babel-polyfill": "^6.26.0",
    "babel-preset-env": "^1.7.0",
    "babel-preset-react": "^6.24.1",
    "css-loader": "^0.28.11",
    "html-loader": "^0.5.5",
    "html-webpack-plugin": "^3.2.0",
    "mini-css-extract-plugin": "^0.4.0",
    "react": "^16.4.1",
    "react-dom": "^16.4.1",
    "webpack": "^4.12.0",
    "webpack-cli": "^3.0.8",
    "webpack-dev-server": "^3.1.4"
  }

Here is my main test app:

import React from "react";
import ReactDOM from "react-dom";
import style from "./main.css";
import pageLoader from './pageLoader';

class App extends React.Component {
    render() {
    let page = pageLoader();  
  return (
    <div>
      <p>React here!</p>
      {page}
    </div>
  );
}
};

export default App;
ReactDOM.render(<App />, document.getElementById("app"));

and my page I want to load dynamically with separate bundle.

import React from "react";
import ReactDOM from "react-dom";
import style from "./main.css";

const Page1 = () => {
  return (
    <div>
      <p>Page1 here!</p>
    </div>
  );
};
export default Page1;

Here's my webpack.config so far:

const path = require('path');
const HtmlWebPackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  entry: {
    polyfill: 'babel-polyfill',
    app: './src/index.js'
  },
    output: {
        filename: '[name].bundle.js',
        chunkFilename: '[name].bundle.js', //name of non-entry chunk files
        path: path.resolve(__dirname, 'dist')
    },

    module: {
        rules: [
            {
                test: /\.(js|jsx)$/,
                exclude: /node_modules/,
                use: {
                    loader: "babel-loader"
                }
            },
            {
        test: /\.html$/,
        use: [
          {
            loader: "html-loader",
            options: { minimize: true }
          }
        ]
      },
      {
        test: /\.css$/,
        use: [MiniCssExtractPlugin.loader, "css-loader"]
      },

        ]
    },

    plugins: [
    new HtmlWebPackPlugin({
        template: "./src/index.html",
        filename: "./index.html"
    }),
    new MiniCssExtractPlugin({
      filename: "[name].css",
      chunkFilename: "[id].css"
    })
    ]
};

Now here's the part that errors on build. Here's the function which calls the dynamic import:

function pageLoader() {
    return import(/* webpackChunkName: "page1" */ './Page1')
    .then(page => {
    return page.default;
    });

}

export default pageLoader;

I get this error on build:

ERROR in ./src/test/pageLoader.js
Module build failed (from ./node_modules/babel-loader/lib/index.js):
SyntaxError: Unexpected token (2:8)

  1 | function pageLoader() {
> 2 |   return import(/* webpackChunkName: "page1" */ './Page1')
    |          ^
  3 |   .then(page => {
  4 |     return page;
  5 |   });

Everything I have read says this is the way to set this up. What am I doing wrong?

Answer

user158 picture user158 · Aug 31, 2018

I was facing the same issue the fix was:

npm install --save-dev @babel/plugin-syntax-dynamic-import

add following line to .babelrc

"plugins": ["@babel/plugin-syntax-dynamic-import"],

Sources: