用于代码拆分的 Webpack 配置不适用于生产构建

Posted

技术标签:

【中文标题】用于代码拆分的 Webpack 配置不适用于生产构建【英文标题】:Webpack config for Code splitting not working for production build 【发布时间】:2017-11-06 15:56:58 【问题描述】:

使用 Webpack 构建 ReactJS 应用程序。最近对使用代码拆分来减小应用程序大小感兴趣。

我已经尝试实现一个包装 System.import() 的自定义 HOC:

/* 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' />;

目前我正在尝试 react-loadable (https://github.com/thejameskyle/react-loadable),这是一个本质上做同样事情但有一些额外的花里胡哨的包。

问题

这两种方法在本地都可以正常工作,但在部署时不起作用。 Webpack 配置源自 2017 年 3 月上旬的 React-Starter-App。我的直觉告诉我,webpack 配置是问题的根源,但我不确定如何调试它。

开发配置(工作)

/* 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)
  ]

暂存配置(不工作)

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',
    ),
  ]

错误: react-loadable 吞下所有错误(手掌+脸),因此我无法从该代码中提供有用的错误。 我的自定义组件会在引导加载程序中引发错误bootstrap 6a12c6c…:54 Uncaught (in promise) TypeError: Cannot read property 'call' of undefined

在我的自定义 HOC 的网络流量中,未加载额外的捆绑包。 在 react-loadable 的网络流量中,bundle 被加载,但从未被处理。

【问题讨论】:

你好! (是的,亲爱的读者)对于提出这个问题的新开发者,谁能告诉我为什么我在这里没有收到任何 cmets/answers/questions? 懒得看 但我也有类似的问题 @TarasLukavyi 支持这个问题,也许我们可以找人帮助我们 我听说缩小代码时 webpack 和分块存在问题。假设它在缩小之前决定如何分块,因此分块可能是不稳定的。值得研究... 【参考方案1】:

这么久了,在升级 Typescript 和 Webpack 之后,结果发现使用 CommonsChunk 插件搞砸了。

尚未调查原因,但将以下内容注释掉:

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

【讨论】:

感谢@robbymurphy 的提示,我很确定你帮我调试了这个

以上是关于用于代码拆分的 Webpack 配置不适用于生产构建的主要内容,如果未能解决你的问题,请参考以下文章

源地图不适用于 Webpack

webpack 4 - 用于多个条目的拆分块插件

代码拆分不适用于 CRA + React Route v4 + 代码拆分

引导日期选择器不适用于 Webpack

React-Webpack-production 构建不适用于 nginx

webpack-dev-server 热重载不适用于 webpack4