webpack优化-代码拆分

一、分离第三方库(vendor)

把第三方代码和应用本身的代码一起打包是非常低效的。
因为浏览器会根据缓存头来缓存资源文件,如果文件没有被改变,文件将会被缓存从而不用去再次请求 cdn。
为了利用这一特性,我们希望不管应用本身的代码如何改变,vendor 文件的 hash 始终恒定不变。

用法:

var webpack = require('webpack');
var path = require('path');

module.exports = function(env) {
    return {
        entry: {
            main: './index.js',
            vendor: 'moment'
        },
        output: {
            filename: '[chunkhash].[name].js',
            path: path.resolve(__dirname, 'dist')
        },
        plugins: [
            new webpack.optimize.CommonsChunkPlugin({
                name: 'vendor' // 指定公共 bundle 的名字。
            })
        ]
    }
}

为第三方库moment添加一个单独的入口vendor,在不使用CommonsChunkPlugin的情况下,webpack运行后会生成两个bundle,并且两个bundle中都会有moment的代码。
CommonsChunkPlugin允许我们从不同的 bundle 中提取所有的公共模块,并且将他们加入公共 bundle 中。如果公共 bundle 不存在,那么它将会创建一个出来。
利用这个特性,我们指定公共bundle的名字与moment的bundle文件一样,从而让CommonsChunkPlugin提取的公共模块覆盖moment的bundle文件,达到分离第三方库的效果。

至此,我们已经成功的将第三方代码提取到了独立的bundle,但上文提到的浏览器缓存机制我们还是无法用上,因为 vendor 的 hash 在每次构建中都会改变,浏览器也必须重新加载文件。

解决方案:

var webpack = require('webpack');
var path = require('path');

module.exports = function(env) {
    return {
        entry: {
            main: './index.js',
            vendor: 'moment'
        },
        output: {
            filename: '[chunkhash].[name].js',
            path: path.resolve(__dirname, 'dist')
        },
        plugins: [
            new webpack.optimize.CommonsChunkPlugin({
                names: ['vendor', 'manifest'] // 指定公共 bundle 的名字。
            })
        ]
    }
};

最终会生成多一个mainfest bundle
更多介绍见 webpack优化-缓存

二、分离CSS

1、导入 CSS

import 'bootstrap/dist/css/bootstrap.css';

2、使用 css-loader

module.exports = {
    module: {
        rules: [{
            test: /\.css$/,
            use: 'css-loader'
        }]
    }
}

结果,CSS和您的JavaScript打包在一起。
这有个缺点,您将无法利用浏览器的异步和并行加载CSS的能力。这样,您的网页必须等待,直到您的整个JavaScript 包下载完成,然后重绘网页。

3、使用 ExtractTextWebpackPlugin
这个插件要自己安装

module.exports = {
    module: {
         rules: [{
             test: /\.css$/,
-            use: 'css-loader'
+            use: ExtractTextPlugin.extract({
+                use: 'css-loader'
+            })
         }]
     },
+    plugins: [
+        new ExtractTextPlugin('styles.css'),
+    ]
}
三、按需分离

虽然前面几类资源分离,需要用户预先在配置中指定分离模块,但也可以在应用程序代码中创建动态分离模块。
这可以用于更细粒度的代码块,例如,根据我们的应用程序路由,或根据用户行为预测。这可以使用户按照实际需要加载非必要资源。

四、使用 require.ensure() 分离代码
require.ensure(dependencies: String[], callback: function(require), chunkName: String)

两种情况:

// 空数组作为参数
require.ensure([], function(require){
    require('./a.js');
});

a.js会被打包到独立的bundle,例如entry打包输出为bundle.js,a.js会被打包为0.bundle.js

//依赖作为参数
require.ensure(['./a.js'], function(require) {
    require('./b.js');
});

上面代码, a.js 和 b.js 都被打包到一起,而且从主文件束中拆分出来。但只有 b.js 的内容被执行。a.js 的内容仅仅是可被使用,但并没有被输出。
想去执行 a.js,我们需要异步地引用它,如 require('./a.js'),让它的 JavaScritp 被执行。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容