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

标签 reactjs webpack react-router chunking code-splitting

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

这是我得到的:

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(开发 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 的两个路由生成单独的包:

  • 智能登陆城市
  • SmartLandingCompanies
  • 关于我们页面

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

感谢您的帮助!

最佳答案

由于已经有三个请求访问包含工作解决方案的存储库,因此它是:) 祝您编码愉快!

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

关于reactjs - 无法让 webpack require.ensure 分块方法与 react 路由器一起使用并生成单独的捆绑文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37943845/

相关文章:

javascript - 在 React 的 render 方法中设置 CSS 变量是个好习惯吗?

reactjs - 排版中的嵌套样式

reactjs - 如何在 React 应用程序中为绝对路径导入启用 VS 代码智能感知?

node.js - 如何从 docker 容器运行 webpack 构建?

javascript - React 组件在 html 脚本标记中未定义

reactjs - 将服务器端渲染添加到 create-react-app

javascript - 如何使用 Jest 0.8.x 测试像 react-router 2.0 中那样使用上下文的 React 组件

javascript - 从子组件更改父状态不起作用

reactjs - 如何清除componentWillUnmount中组件存储的redux状态?

reactjs - React-Router v4 onEnter 替换