生产环境下的代码分割Webpack配置不起作用

8

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

我尝试实现一个自定义HOC来包装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'} />;
}

目前我正在尝试使用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

在我的自定义高阶组件的网络流量中,额外的bundle未被加载。 在react-loadable的网络流量中,该bundle被加载,但从未被处理。


嗨!(是的,亲爱的读者)对于新开发人员来说,有没有人能告诉我为什么我在这里没有收到任何评论/答案/问题? - sean.hudson
太懒了,不想读。 - Taras Lukavyi
但是我有类似的问题。 - Taras Lukavyi
@TarasLukavyi 给这个问题点个赞,也许我们能找到帮助我们的人。 - sean.hudson
我遇到了相同的问题,但是在Vue.js中。 - RoboKozo
1
我听说在压缩代码时,webpack和分块存在问题。据说它在压缩之前就决定了如何分块,因此分块可能会出现错误。值得深入研究一下... - robbymurphy
1个回答

1

经过所有这些时间,升级Typescript和Webpack之后,结果发现使用CommonsChunk插件会出现一些问题。

还没有调查原因,但是注释掉以下内容可以解决问题:

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

感谢@robbymurphy的提示,我相信你帮助我调试了这个问题。 - sean.hudson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接