Webpack2 tree shaking 之旅

背景:最近webpack升级了2.0的版本,支持代码静态依赖解析打包了。吓得我赶紧弄个小demo出来试试水。本文默认读者都有一定的webpack使用经验,没使用过webpack的同学最好先看下相关文档。

静态依赖打包可以去掉很多无用的代码,减少文件体积。下面两张图片是楼主打包的两个文件,一个是使用tree shaking,一个是没使用的,都是为了引用一个方法encodeHTML。对比下生成文件的差异。

普通require模式引入

 Webpack2 tree shaking 之旅_第1张图片

es6 tree shaking

 Webpack2 tree shaking 之旅_第2张图片

可以看到tree shaking 只打包了我们需要的那个方法。楼主的demo支持打包多页面,地址在最下面,各位小伙伴可以自己clone下来看看。

看完了tree shaking的效果,下面我们来讨论以下几点

1. 如何开启webpack2tree shaking功能

2. Webpack2配置注意事项

3. ES6模块编写注意事项

4.  一些配置优化点

如何开启webpack2tree shaking功能

首先,只有es6模块才能使用webpack2做静态依赖解析。因为现在大部分浏览器还不支持es6模块语法,所以我们得下载babel,利用babel对代码进行编译。正常使用Babel 6来转换,一般设置presets: ['es2015']。但是这种方式使用的 transform-es2015-modules-commonjs插件意味着Babel会将es6模块通过commonJs模块转换输出,然后webpack 2就不能进行tree-shaking分析了。我的办法是修改babel的设置

//关键代码,只有去掉babel的cjs模块,才能做tree shaking打包
test: /\.js$/,
loader:'babel',
query: {
    cacheDirectory: true,
    plugins: [
        'transform-es2015-template-literals',
        'transform-es2015-literals',
        'transform-es2015-function-name',
        'transform-es2015-arrow-functions',
        'transform-es2015-block-scoped-functions',
        'transform-es2015-classes',
        'transform-es2015-object-super',
        'transform-es2015-shorthand-properties',
        'transform-es2015-computed-properties',
        'transform-es2015-for-of',
        'transform-es2015-sticky-regex',
        'transform-es2015-unicode-regex',
        'check-es2015-constants',
        'transform-es2015-spread',
        'transform-es2015-parameters',
        'transform-es2015-destructuring',
        'transform-es2015-block-scoping',
        'transform-es2015-typeof-symbol',
        ['transform-regenerator', {async: false, asyncGenerators: false}]
]
}
exclude: /node_modules/

Webpack2配置注意事项

Webpack2相对webpack1做了一些配置的更改,更改的配置比较多,这里只是简单的介绍下几个影响构建的部分

Resolve option

webpack1中,文件路径查找的resolve.root属性被删除了,取代的是resolve.module属性。

Plugins

//webpack.optimize.OccurenceOrderPlugin插件不再需要配置
//ExtractTextPlugin配置方式变更, ExtractTextPlugin需要更新到2.0版本。新老配置方式对比:
Webpack1 : ExtractTextPlugin.extract('css!postcss!sass')
Webpack2: ExtractTextPlugin.extract({
                    fallbackLoader: "style-loader",
                    loader: "css-loader?minimize"
                })
//CommonsChunkPlugin配置方式变更
Webpack1:CommonsChunkPlugin('common/common','js/[name].js')
Webpack2:CommonsChunkPlugin({name:'commonFile',filename:'js/[name].[hash:8].js' })

HMR communication

Webpack 1 中,更新信号用的是Web Messaging APIpostMessage)。而Webpack 2将使用一个标准的事件触发器来传递事件信号。这表示WebSocket必须内联到打包文件中。webpack-dev-server必须使用新版本

更多配置可以看楼主的demo和下文参考资料中的链接

ES6模块编写注意事项

Webpack2支持新的异步加载模块方法System.import。使用这个方法可以返回一个promise对象,模块加载失败可以被捕获,支持动态模块名,每个动态模块都会产生新的chunk文件。异步加载的文件,没必要分别导出模块的方法。

示例代码

function route(path, query) {
   return System.import("./routes/" + path + "/route")
        .then(route => new route.Route(query));
}

这会为每种可能的路径组合都创建一个对应的chunk

非异步的模块,使用export关键字,导出函数和变量,在构建时,才可以分析依赖进行构建。

示例代码

export function encodeHTML(str) {
    if (typeof str == 'string') {
        var ar = ['&', '&', '<', '<', '>', '>', '"', '"'];
        for (var i = 0; i < ar.length; i += 2) {
            str = str.replace(new RegExp(ar[i], 'g'), ar[1 + i]);
        }
        return str;
    }
    return str;
}
 
export var a = ['hello world'];
 
//引用
import {encodeHTML} from 'util/string_es6'

一些配置优化点

UglifyJsPlugin配置output.max_line_len属性,指定压缩文件的单行最大长度,方便在线上代码出现js问题的时候可以快速定位到出错的代码位于哪一行。

webpack.DllPlugin打包不怎么改动的文件,提高构建速度。

babel打包默认会加上use strict,如果使用了argument.calleejs代码。会导致一些语法错误。可以使用插件babel-plugin-transform-remove-strict-mode或者用gulp全局替换下。

demo地址:https://github.com/xyc-cn/webpack2-demo/tree/master

参考资料

Babel use strict https://github.com/shanggqm/blog/issues/1

Webpack1 to webpack2 https://github.com/cssmagic/blog/issues/58

Webpack2 tree shaking http://www.2ality.com/2015/12/webpack-tree-shaking.html

Webpack2 demo https://github.com/phiphou/webpack-es6-demo

 

你可能感兴趣的:(webpack)