Webpack config for Code splitting not working for production build

孤街醉人 提交于 2020-01-02 02:44:10

问题


Building a ReactJS application with Webpack. Recently interested in using code splitting to reduce app size.

I've tried implementing a custom HOC that wrapped System.import():

/* async/index.tsx */
... at a very high level looked like...
class Async extends React ... {
    componentWillMount() {
        this.props.load.then(c => {
            this.component = c;
            this.setState({loaded:true});
        }
    }
    render() {
        return this.component ? <this.component.default {...this.props} /> : <span />;
    }
}

/* async/foo/index.tsx */
import Async from 'async';
const Foo = (props) => (
    <Async
      {...props}
      load={System.import('async/foo/body')}
    />);

class Foo ... {
    ...
    render = () => <Foo myProp={'bar'} />;
}

Currently I'm trying react-loadable (https://github.com/thejameskyle/react-loadable), a package that does essentially the same thing but with some extra bells n whistles.

Problem

Both methods work fine locally, but do not work when deployed. Webpack configurations are derived from React-Starter-App, from early March 2017. My gut tells me that the webpack config is the source of the problem, but I'm not sure how to debug this.

Dev Config (works)

/* relevant configs */
module.exports = {
  entry: [
      require.resolve('react-dev-utils/webpackHotDevClient'),
      require.resolve('./polyfills'),
      paths.appIndexJs
  ],
  output: {
    path: paths.appBuild,
    pathinfo: true,
    filename: 'static/js/bundle.js',
    publicPath: publicPath
  },
  ...
  plugins: [
    new ExtractTextPlugin({filename: 'style.css', allChunks: true}),
    new InterpolateHtmlPlugin(env.raw),
    new HtmlWebpackPlugin({
      inject: true,
      template: paths.appHtml,
    }),
    new BundleAnalyzerPlugin(),
    new webpack.DefinePlugin(env.stringified),
    new webpack.HotModuleReplacementPlugin(),
    new CaseSensitivePathsPlugin(),
    new webpack.LoaderOptionsPlugin({
      debug: true
    }),
    new WatchMissingNodeModulesPlugin(paths.appNodeModules)
  ]
}

Staging Config (not working)

module.exports = {
  bail: true,
  devtool: 'source-map',
  entry: [
    require.resolve('./polyfills'),
    paths.appIndexJs
  ],
  output: {
    path: paths.appBuildStaging,
    filename: 'static/js/[name].[chunkhash:8].js',
    chunkFilename: 'static/js/[name].[chunkhash:8].chunk.js',
    publicPath: publicPath,
  },
  resolve: {
    modules: ['node_modules', paths.appNodeModules].concat(paths.nodePaths).concat(paths.appSrc),
    extensions: ['.ts', '.tsx', '.scss', '.js', '.json', '.jsx']
  },
  ...
  plugins: [
    new InterpolateHtmlPlugin(env.raw),
    new HtmlWebpackPlugin({
      inject: true,
      template: paths.appHtml,
      minify: {
        removeComments: true,
        collapseWhitespace: true,
        removeRedundantAttributes: true,
        useShortDoctype: true,
        removeEmptyAttributes: true,
        removeStyleLinkTypeAttributes: true,
        keepClosingSlash: true,
        minifyJS: true,
        minifyCSS: true,
        minifyURLs: true,
      },
    }),
    new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor',
      minChunks: function (module) {
        // this assumes your vendor imports exist in the node_modules directory
        return module.context && module.context.indexOf('node_modules') !== -1;
      }
    }),
    //CommonChunksPlugin will now extract all the common modules from vendor and main bundles
    new webpack.optimize.CommonsChunkPlugin({ 
      name: 'manifest' //But since there are no more common modules between them we end up with just the runtime code included in the manifest file
    }),
    new BundleAnalyzerPlugin(),
    new webpack.DefinePlugin(env.stringified),
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        screw_ie8: true, //. React doesn't support IE8
        warnings: false,
        drop_console: false,
      },
      mangle: {
        screw_ie8: true,
      },
      output: {
        comments: false,
        screw_ie8: true,
      },
      sourceMap: true,
    }),
    new ExtractTextPlugin({
      filename: cssFilename,
    }),
    new ManifestPlugin({
      fileName: 'asset-manifest.json',
    }),
  ]
}

Errors: react-loadable swallows all errors (palm + face) so I'm not able to provide useful errors from that code. My custom component would throw an error in the bootstrap loader bootstrap 6a12c6c…:54 Uncaught (in promise) TypeError: Cannot read property 'call' of undefined

In the network traffic for my custom HOC, the extra bundle is not loaded. In the network traffic for react-loadable, the bundle is loaded, but it is never processed.


回答1:


So after all this time, after upgrading Typescript and Webpack, it turns out that using the CommonsChunk plugin was screwing it up somehow.

Have not yet investigated why, but commenting out the following worked:

// new webpack.optimize.CommonsChunkPlugin({
//   name: 'vendor',
//   minChunks: function (module) {
//     return module.context && module.context.indexOf('node_modules') !== -1;
//   }
// }),


来源:https://stackoverflow.com/questions/44376355/webpack-config-for-code-splitting-not-working-for-production-build

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!