无法让 webpack require.ensure 分块方法与 react-router 一起使用并生成单独的捆绑文件

Posted

技术标签:

【中文标题】无法让 webpack require.ensure 分块方法与 react-router 一起使用并生成单独的捆绑文件【英文标题】:Can't get webpack require.ensure chunking method to work with react-router and generate separate bundle files 【发布时间】:2016-10-22 23:13:37 【问题描述】:

我想使用 webpack 分块方法在我的路由配置中为单独的路由生成单独的包。 实现它的一种方法是使用 require.ensure 定义块的拆分点并根据浏览器的需求异步加载模块。

这是我得到的:

webpack.config.js(根据执行的 npm 脚本与 dev/prod webpack 配置合并):

var autoprefixer = require('autoprefixer');
var html         = require('html-webpack-plugin');
var path         = require('path');
var webpack = require('webpack');

var node_modules_dir = path.resolve('./node_modules')

var HappyPack = require('happypack');

module.exports = 
  context: path.resolve('./src'),
  entry: 
    app: ['./scripts/index.js', './styles/index.scss'],
    vendor: ['react', 'react-dom', 'react-redux', 'redux','immutable'],
  ,
  module: 
    loaders: [
      
        test: /\.(jpg|png|gif|json)$/,
        loader: 'file',
        query: 
          name: 'assets/[hash].[ext]',
        ,
      ,
      
        test: /\.svg$/,
        loader: 'happypack/loader?id=svg'
      ,
    ],
  ,
  output: 
    filename: '[name].js',
    path: path.resolve('./build'),
  ,
  plugins: [
    new webpack.optimize.OccurrenceOrderPlugin(),
    // new webpack.optimize.LimitChunkCountPlugin(maxChunks: 5),
    // new webpack.optimize.MinChunkSizePlugin(minChunkSize: 10000),
    new html(
      minify: 
        collapseWhitespace: true,
      ,
      template: './index.html',
      title: process.env.npm_package_config_title,
    ),
    new webpack.optimize.CommonsChunkPlugin('vendor','vendor.bundle.js'),
    new HappyPack(
      id: 'svg',
      threads: 5,
      loaders: [
        'svg-inline'
      ]
    )
  ],
  postcss: function() 
    return [
      autoprefixer,
    ];
  ,
  resolve: 
    alias: 
      assets: path.resolve('./src/assets'),
      lib: path.resolve('./src/lib'),
      modules: path.resolve('./src/scripts/modules'),
      scripts: path.resolve('./src/scripts'),
      styles: path.resolve('./src/styles'),
      toolbox: path.resolve('./node_modules/react-toolbox'),
      vendors: path.resolve('./src/vendors'),

      'react-redux': node_modules_dir + '/react-redux/dist/react-redux.min.js',
      'redux': node_modules_dir + '/redux/dist/redux.min.js',
      'immutable': node_modules_dir +'/immutable/dist/immutable.min.js'
    ,
    extensions: [
      '',
      '.js',
      '.jsx',
      '.css',
      '.scss',
    ],
  ,
  toolbox: 
    theme: path.resolve('./toolbox/index.scss'),
  ,
;

webpack.config.dev.js(dev webpack配置[与上面合并]):

var merge   = require('webpack-merge');
var webpack = require('webpack');
var path    = require('path');
var config  = require('./config');

var HappyPack = require('happypack');
var ExtractTextPlugin = require("extract-text-webpack-plugin");

module.exports = merge(config, 
  // devtool: 'eval',
  devServer: 
    contentBase: 'build',
    historyApiFallback: true,
    hot: true,
    host: '0.0.0.0',
    inline: true,
    port: parseInt(process.env.npm_package_config_port),
  ,
  module: 
    loaders: [
      
        test: /\.jsx?$/,
        exclude: /node_modules/,
        loader: 'happypack/loader?id=jsx'
      ,
      
        test: /\.s?css$/,
        loader: 'happypack/loader?id=css'
      ,
    ],
  ,
  output: 
    chunkFilename: "[name].js",
    publicPath: 'http://localhost:' + process.env.npm_package_config_port + process.env.npm_package_config_public_path,
    pathInfo: true,
  ,
  plugins: [
    new webpack.PrefetchPlugin('react'),
    new webpack.PrefetchPlugin('react-toolbox'),
    new webpack.PrefetchPlugin('react-redux'),
    new webpack.PrefetchPlugin('redux'),
    new webpack.PrefetchPlugin('immutable'),
    new webpack.PrefetchPlugin('./scripts/routes.jsx'),

    new webpack.PrefetchPlugin('./scripts/components/smart/index.jsx'),
    new webpack.PrefetchPlugin('./scripts/components/views/login/index.jsx'),
    new webpack.PrefetchPlugin('./scripts/components/views/companies_list/index.jsx'),
    new webpack.PrefetchPlugin('./scripts/components/views/shortlists/index.jsx'),
    new webpack.PrefetchPlugin('./scripts/components/views/testing_shortlist/index.jsx'),
    new webpack.PrefetchPlugin('./scripts/components/views/tools/components/index.jsx'),
    new webpack.PrefetchPlugin('./scripts/components/views/tools/horizontal_chart/index.jsx'),
    new webpack.PrefetchPlugin('./scripts/components/views/tools/smarts/index.jsx'),
    new webpack.PrefetchPlugin('./scripts/components/views/tools/view_content/index.jsx'),
    new webpack.PrefetchPlugin('./scripts/components/views/tools/views/index.jsx'),

    new webpack.PrefetchPlugin('./scripts/components/views/tools.old/refactorized_tools/components/index.jsx'),
    new webpack.PrefetchPlugin('./scripts/components/views/tools.old/refactorized_tools/composed/index.jsx'),
    new webpack.PrefetchPlugin('./scripts/components/views/tools.old/refactorized_tools/view_content/index.jsx'),
    new webpack.PrefetchPlugin('./scripts/components/views/tools.old/refactorized_tools/views/index.jsx'),

    new webpack.PrefetchPlugin('./scripts/components/views/tools.old/tools/cities_list_with_filters/index.jsx'),
    new webpack.PrefetchPlugin('./scripts/components/views/tools.old/tools/city_path_start/index.jsx'),
    new webpack.PrefetchPlugin('./scripts/components/views/tools.old/tools/company_path_start/index.jsx'),
    new webpack.PrefetchPlugin('./scripts/components/views/tools.old/tools/compare_cities_datapoints/index.jsx'),
    new webpack.PrefetchPlugin('./scripts/components/views/tools.old/tools/compare_companies_datapoints/index.jsx'),
    new webpack.PrefetchPlugin('./scripts/components/views/tools.old/tools/compare_result/index.jsx'),
    new webpack.PrefetchPlugin('./scripts/components/views/tools.old/tools/scan_your_brand/index.jsx'),
    new webpack.PrefetchPlugin('./scripts/components/views/tools.old/tools/subcomponents/index.jsx'),

    new webpack.PrefetchPlugin('./lib/ui/multi_select/RTAutocomplete/index.js'),

    new webpack.PrefetchPlugin('./scripts/components/views/tools/view_content/charts/style/charts.scss'),
    new webpack.PrefetchPlugin('./scripts/components/views/tools/view_content/filters_box/style/city.scss'),
    new webpack.PrefetchPlugin('./scripts/components/views/tools/view_content/filters_box/style/company.scss'),
    new webpack.PrefetchPlugin('./scripts/components/views/tools/view_content/map_with_bottom_stats/style.scss'),
    new webpack.PrefetchPlugin('./scripts/components/views/tools/view_content/city_boxes/style/city_boxes.scss'),
    new webpack.PrefetchPlugin('./scripts/components/views/tools/view_content/company_boxes/style/company_boxes.scss'),
    new webpack.PrefetchPlugin('./scripts/components/views/tools/view_content/filters_box_with_header_box/style/city.scss'),
    new webpack.PrefetchPlugin('./scripts/components/views/tools/view_content/filters_box_with_header_box/style/company.scss'),
    new webpack.PrefetchPlugin('./scripts/components/views/tools/view_content/selected_entities/style/selected_entities.scss'),
    new webpack.PrefetchPlugin('./scripts/components/views/tools/view_content/human_resources_table_box/style/_human_resources_table_box.scss'),
    // new webpack.PrefetchPlugin(''),
    new ExtractTextPlugin("[hash].css"),
    new webpack.DefinePlugin(
      'process.env.NODE_ENV': JSON.stringify('development'),
      'process.env.LANDING_ONLY': JSON.stringify(false),
    ),
    new webpack.HotModuleReplacementPlugin(),
    new HappyPack(
      id: 'jsx',
      threads: 5,
      loaders: ['babel?presets[]=react-hmre']
    ),
    new HappyPack(
      id: 'css',
      threads: 5,
      loaders: [
        'style',
        'css?sourceMap,modules,localIdentName=[local]__[hash:base64:5]',
        'postcss',
        'resolve-url',
        'sass?sourceMap',
        'toolbox'
      ]
    )
  ],
);

routes.jsx

[some module imports here]

export default (
  <Route component= PermisionProvider  >
    <Route component= AppProvider  >
      <Route component= SnackbarProvider  >
        <Redirect from= paths.root  to= localStorage.get('user') ? paths.login : paths.landingPageCities  />


         /* Landing */ 
        <Route onEnter= _hasPermission.bind(null, 'landingPage') >
          <Route component= LandingLayout >
            <Route 
              path= paths.landingPageCities    
              getComponent=(location, callback) => 
                    require.ensure(['modules/landing_page/smarts/SmartLandingCities'], function (require) 
              callback(null, require('modules/landing_page/smarts/SmartLandingCities').default);
            , 'SmartLandingCities');
           
        />
        <Route 
          path= paths.landingPageCompanies 
          getComponent=(location, callback) => 
            require.ensure(['modules/landing_page/smarts/SmartLandingCompanies'], function (require) 
              callback(null, require('modules/landing_page/smarts/SmartLandingCompanies').default);
            , 'SmartLandingCompanies');
           
        />
        <Route 
          path= paths.aboutUsPage           
          getComponent=(location, callback) => 
            require.ensure(['modules/landing_page/views/AboutUsPage'], function (require) 
              callback(null, require('modules/landing_page/views/AboutUsPage').default);
            , 'AboutUsPage');
           
        />
      </Route>
    </Route>

     /* Login */ 
    <Route onEnter= _hasPermission.bind(null, 'login') >

我阅读了大量的博客文章和教程,这一切似乎都在这里。然而,webpack 并没有为我使用 require.ensure 的两个路由生成单独的包:

SmartLandingCities SmartLandingCompanies 关于我们页面

我已经非常绝望了,因为应用程序包的大小为 2mb,而且我已经使用了所有可用的大小缩小方法。

感谢您的帮助!

【问题讨论】:

Using webpack and react-router for lazyloading and code-splitting not loading的可能重复 @azrahel,我也遇到了同样的问题,也发布了一个问题***.com/questions/39757297。虽然查看您的 webpack.config 文件,但您没有定义 chunkFilename: "[name].js" 而在 dev config 中您定义了。尝试在生产配置中添加它。如果你已经解决了,请告诉我。 嘿,是的,已经解决了。我真的不记得确切的问题是什么,但我可以向您发送我最近开始的小项目,上面的代码正常工作。 那太棒了。如果它在 github 上,你能发布项目的链接吗? @azrahel 如果您有其他喜欢的方法,请告诉我。 【参考方案1】:

由于已经有三个请求访问包含工作解决方案的 repo,所以这里是:) 祝您编码愉快!

https://bitbucket.org/azrahel/crit_calendar/

【讨论】:

以上是关于无法让 webpack require.ensure 分块方法与 react-router 一起使用并生成单独的捆绑文件的主要内容,如果未能解决你的问题,请参考以下文章

无法让多应用 webpack 配置与 react-hot-loader 一起使用

无法让 webpack require.ensure 分块方法与 react-router 一起使用并生成单独的捆绑文件

与 Webpack 捆绑时,无法使 Tether 为 Bootstrap 4 工作

Webpack 无法正确解析我的别名

webpack中的eslint导入:无法解析模块的路径

无法使用 webpack 在依赖项上加载 angularjs $templateCache 模板