3

I am using [email protected] and [email protected] to build a dashboard template and trying to generate chunk files from dynamic import but the files are never generated. :( I could render the component which is imported and rendered but it seems the file is not made and the component is not dynamically imported.

What I did

  • Set "syntax-dynamic-import" and "dynamic-import-webpack" to babel plugin
  • Added chunkFilename to webpack output

What I expected

  • Generate chunk file out of dynamic import based on route

Version

  • "react": "^16.0.0"
  • "react-dom": "^16.0.0"
  • "react-router": "^4.2.0"
  • "react-router-dom": "^4.2.2"
  • "babel-plugin-dynamic-import-webpack": "^1.0.1"
  • "babel-plugin-syntax-dynamic-import": "^6.18.0"
  • "webpack": "3.1.0"

Here is my .babelrc

{
  "presets": [
    "react",
    ["env", {
      "targets": {
        "browsers": ["last 2 versions", "safari >= 7"]
      }
    }]
  ],
  "plugins": [
    "syntax-dynamic-import",
    "dynamic-import-webpack",
    "transform-export-extensions",
    "transform-class-properties",
    ["transform-runtime", {
      "polyfill": false,
      "regenerator": true
    }],
    ["transform-object-rest-spread", {
      "useBuiltIns": true
    }]
  ]
}

And this is App.jsx and I tried to make chunk file out of Dashboard1

const loadDashboard1 = import(/* webpackChunkName: "dashboard1" */ '../Dashboard1/index.jsx')

const Dashboard1 = (props) => <AsyncComponent lazyLoadComponent={loadDashboard1} props={props} /> 
const Dashboard = () => (
  <div>
    <Switch>
      <Route path="/dashboard/1" component={Dashboard1} /> //*** This should be dynamic imported and make chunk file
      <Route path="/dashboard/2" component={Dashboard2} />
      <Route path="/dashboard/3" component={Dashboard3} />
    </Switch>
  </div>
)


const App = () => (
  <div className={wrapper}>
    <HeaderMain />
    <Route path="/dashboard" component={SidebarLeft} />
    <main className={content}>
      <Switch>
        <Route path="/dashboard" component={Dashboard} />
        <Route path="/" component={HomePage} />
      </Switch>
    </main>
  </div>
)

export default App

Here is my webpack.config.js. I added chunkFilename

const webpack = require('webpack');
const path = require('path');
const HTMLWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');

module.exports = {
  devtool: 'source-map',
  target: 'web',
  node: {
    __dirname: true,
    fs: 'empty'
  },
  entry: {
    'main': './client/index.js',
    'vendor': ['react', 'react-dom']
  },
  output: {
    path: path.resolve(__dirname, '../public'),
    filename: '[name].[chunkhash].js',
    chunkFilename: '[name].[chunkhash].js',
    publicPath: "/public",
  },
  module: {
    rules: [
      {
        test: /\.(js|jsx)?$/,
        exclude: /node_modules/,
        loader: 'babel-loader',
      }, {
        test: /\.css$/,
        use: [{
          loader: 'style-loader',
        }, {
          loader: 'css-loader',
        }]
      }, {
        test: /\.(scss)?$/,
        exclude: /node_modules/,
        use: [
          {
            loader: 'style-loader',
          }, {
            loader: 'css-loader',
            options: {
              modules: true,
              localIdentName: '[name]__[local]___[hash:base64:5]',
            }
          }, {
            loader: 'postcss-loader',
            options: {
              config: {
                path: 'postcss.config.js'
              }
            }
          }, {
            loader: 'sass-loader',
          }
        ]
      }
    ]
  },
  plugins: [
    new HTMLWebpackPlugin({
      title: ''
    }),
    new CleanWebpackPlugin([path.resolve(__dirname, '../public')], {
      root: path.resolve(__dirname, '../'),
    })
  ]
};

Here is AsyncComponent.

import React from 'react'

class AsyncComponent extends React.Component {

  state = {
    Component: null,
    isLoaded: false,
  }

  async componentWillMount() {
    const module = await this.props.lazyLoadComponent
    this.setState({
      Component: module.default ,
      isLoaded: true,
    })
  }

  render() {
    const { Component } = this.state
    return (
      <div>{this.state.isLoaded ? <Component /> : this.props.loader}</div>
    )
  }
}


export default AsyncComponent

This is the result out of webpack

   main.5227b4d762a52f00aeb2.js     262 kB       0  [emitted]  [big]  main
    vendor.478de73b0c92dd129de6.js     116 kB       1  [emitted]         vendor
  main.5227b4d762a52f00aeb2.js.map    1.53 MB       0  [emitted]         main
vendor.478de73b0c92dd129de6.js.map     420 kB       1  [emitted]         vendor
                        index.html  297 bytes          [emitted]

If you have any idea to solve this issue or need further information, please let me know.

Thank you!

1
  • It's refreshing to see a solid question laid out with attempts and expectations, kudos! Commented Oct 27, 2017 at 1:24

1 Answer 1

1

Everything looks perfect, minus the dynamic-import-webpack, which isn't needed in webpack 2+. My guess is that you imported this component somewhere else on accident, so the bundle wasn't created :)

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

1 Comment

I accidentally imported the component in a static way from other files, which causes that chunk file was not generated.

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.