Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get dynamic imports to work in webpack 4

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?

like image 225
Coco Avatar asked Jun 21 '18 20:06

Coco


People also ask

How do dynamic imports work webpack?

Whenever you import a file in your code, Webpack will look for it in the project directory and copy it to the build folder with a new name, then Webpack replaces the import code in your bundled JavaScript file with the path to the newly copied file.

How do dynamic imports work?

Dynamic import of modulesIt returns a promise and starts an asynchronous task to load the module. If the module was loaded successfully, then the promise resolves to the module content, otherwise, the promise rejects.

Does webpack support import?

The imports loader allows you to use modules that depend on specific global variables. This is useful for third-party modules that rely on global variables like $ or this being the window object. The imports loader can add the necessary require('whatever') calls, so those modules work with webpack.

Is dynamic import cached?

Once a module is fetched dynamically from the server, it is cached permanently on the client and additional requests for the same version of the module will not incur the round-trip request to the server. If the module is changed then a fresh copy will always be retrieved from the server.


1 Answers

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:

  • https://webpack.js.org/guides/code-splitting/#dynamic-imports

  • https://babeljs.io/docs/plugins/syntax-dynamic-import/#installation

like image 165
user158 Avatar answered Sep 18 '22 14:09

user158