在 React 项目中使用 System.import 进行 Tree Shaking 和延迟加载的 Webpack 2 配置

Posted

技术标签:

【中文标题】在 React 项目中使用 System.import 进行 Tree Shaking 和延迟加载的 Webpack 2 配置【英文标题】:Webpack 2 configuration for Tree shaking and lazy loading with System.import on React project 【发布时间】:2017-06-14 04:44:30 【问题描述】:

我是 webpack 2 的新手,它是延迟加载,到目前为止,我已经创建了没有延迟加载和代码拆分的项目,但现在想将我的代码拆分成块并使用 React Router 的系统导入。我根据this 文章创建了 React Router 部分

这个 webpack 2 配置文件在下面。

let webpack = require('webpack');
let path = require('path');
let ExtractTextPlugin = require('extract-text-webpack-plugin');

var devFlagPlugin = new webpack.DefinePlugin(
    __DEV__: JSON.stringify(JSON.parse(process.env.DEBUG || 'false')),
    'process.env': 
        NODE_ENV: JSON.stringify(process.env.NODE_ENV || 'development'),
    
);

let extractSCSS = new ExtractTextPlugin('[name].css')

module.exports = 
    context: __dirname,
    entry: 
        bundle: './src/app/app-client.jsx',
        styles: './src/app/sass/main.scss',
        vendor: [
            'react', 'react-dom'
        ]
    ,
    output: 
        filename: '[name].js',
        chunkFilename: 'chunk.[id].[chunkhash:8].js',
        path: './src/build',
    ,
    resolve: 
        extensions: ['.js', '.jsx']
    ,
    devtool: 'cheap-module-source-map',
    module : 
        rules : [
            
                test: /\.scss$/,
                loader: extractSCSS.extract(['css-loader','sass-loader'])
            ,
            
                test: /\.jsx?$/,
                exclude: [/node_modules/, /libs/],
                use: 
                    loader: "babel-loader",
                    query: 
                        presets: ['es2015', 'react', 'stage-2' ],
                        plugins: [ "transform-runtime" ]
                    
                
            ,
            
                test: /\.woff2?$|\.ttf$|\.eot$|\.svg$|\.png|\.jpe?g|\.gif$/,
                use: 
                    loader:'file-loader'
                
            
        ]
    ,
    plugins: [
        extractSCSS,
        devFlagPlugin,
        new webpack.optimize.CommonsChunkPlugin(
            name: 'bundle',
            children: true,
            async: true,
            minChunks: 2
        ),
        new webpack.optimize.CommonsChunkPlugin(
            name: 'vendor',
            children: true,
            async: true,
            minChunks: 2
        )
    ]

但是 webpack 只创建了两个文件,vendor 和 bundle,而且在我分离 React 和 React DOM 之后,bundle 的大小并没有减少。

这是我的路线。

import App from './App.jsx';

function errorLoading(err) 
  console.error('Dynamic page loading failed', err);


function loadRoute(cb) 
  return (module) => cb(null, module.default);


export default 
  component: App,
  childRoutes: [
    
      path: 'stock/info/:symbol(/:tab)',
      getComponent(location, cb) 
        System.import('./StockPage')
          .then(loadRoute(cb))
          .catch(errorLoading);
      
    ,
    
      path: '*',
      getComponent(location, cb) 
        System.import('./NoMatch')
          .then(loadRoute(cb))
          .catch(errorLoading);
      
    
  ]
;

我的应用程序运行,但延迟加载当然不起作用,因为System.import 中没有我的模块块。

请帮助我为我的应用程序的性能创建正确的 webpack 配置! 提前感谢,如果有什么废话,我很抱歉,因为我是 webpack 的新手。

【问题讨论】:

【参考方案1】:

Webpack2 从 System.import() 切换到 import() 以匹配当前提议的 javascript 功能。现在处于第3阶段。

所以你应该能够更改你的 webpack 配置以包含 STAGE-3


            test: /\.jsx?$/,
            exclude: [/node_modules/, /libs/],
            use: 
                loader: "babel-loader",
                query: 
                    presets: ['es2015', 'react', 'stage-2', 'stage-3' ],
                    plugins: [ "transform-runtime" ]
                
            
,

或者动态导入插件


            test: /\.jsx?$/,
            exclude: [/node_modules/, /libs/],
            use: 
                loader: "babel-loader",
                query: 
                    presets: ['es2015', 'react', 'stage-2' ],
                    plugins: [ "transform-runtime", "syntax-dynamic-import"]
                
            
,

然后改变你的路线

export default 
  component: App,
  childRoutes: [
  
    path: 'stock/info/:symbol(/:tab)',
    getComponent(location, cb) 
      import('./StockPage')
        .then(loadRoute(cb))
        .catch(errorLoading);
    
  ,
  
    path: '*',
    getComponent(location, cb) 
    import('./NoMatch')
      .then(loadRoute(cb))
      .catch(errorLoading);
    
  
]
;

有关使用 import 进行代码拆分和延迟加载的完整文档,请参阅此处的 webpack2 帮助页面。 https://webpack.js.org/guides/migrating/#code-splitting-with-es2015 https://github.com/tc39/proposal-dynamic-import

启用 Webpack2 摇树只需要对你的 babel 设置进行一次更改。

presets: ['es2015', 'react', 'stage-2' ],

变成

presets: [['es2015',  modules: false ], 'react', 'stage-2' ],

这是我从 https://medium.freecodecamp.com/tree-shaking-es6-modules-in-webpack-2-1add6672f31b#.lv3ldgfhs 发现的有关 treeshaking 的文章

【讨论】:

这是在 webpack 2 中使用动态导入的正确方法。 实际上对于 webpack 你需要babel-plugin-dynamic-import-webpack 来转换 import() 语句,而不是 babel-plugin-syntax-dynamic-import。 babel-plugin-syntax-dynamic-import 只允许 babel 解析动态导入,但不转换它们。 @ismay 对于 WebPack V1 来说是这样,但 Webpack2 现在原生支持 ES6 导入和 import() 函数。 @DanielD 嗯,这很奇怪。对我来说,如果没有那个插件,它会因unknown node of type "Import" with constructor "Node" 而失败,使用 webpack 2.2.0。但是使用 dynamic-import-webpack 可以正常工作。

以上是关于在 React 项目中使用 System.import 进行 Tree Shaking 和延迟加载的 Webpack 2 配置的主要内容,如果未能解决你的问题,请参考以下文章

如何将 React 组件导出为 NPM 包以在单独的项目中使用?

在react-native 项目中使用yarn link

在 React 项目中使用 Axios 的目的 [关闭]

在 React Native 项目中使用 npm 模块

在 React 项目中使用 Material ui 和 Tailwind css

无法在我的项目中解析“react-native”