Webpack2 初识
栏目: JavaScript · 发布时间: 8年前
内容简介:Webpack2 初识
聚焦webpack2的部分目录:
温故或知新
简单地概括--webpack是一个智能模块依赖分析的打包工具,它通过入口js文件以及一系列的插件能把各种资源文件编译、打包为可发布使用的静态资源。如官网中的视图:万物皆模块。
安装
文章撰写时webpack最新正式版版本号为2.5.1。
命令行 工具 中安装:
# 全局安装 npm install -g webpack # 初始化项目 npm init #安装到项目目录中 npm install --save-dev webpack
快速开始
在根目录创建如下文件:
entry.js -- 入口文件
import fn from './fn'; fn();
fn.js -- 被引用的模块
export default function fn() {
document.write('I am a Function');
}
webpack.config.js -- webpack配置文件
module.exports = {
entry: './entry.js',
output: {
filename: 'bundle.js'
}
}
index.html -- 静态页面
<!DOCTYPE html>
<html>
<body>
<script src="./bundle.js"></script>
</body>
</html>
在项目目录中执行命令 webpack ,然后在浏览器打开上面的静态页面就可以看到效果了
变化
现在简单列出我认为对比webpack1版比较明显的变化
-
ES6模块的静态导入(import等部分ES6语法的原生支持): 更快捷的初始化工程
-
ES6模块的动态导入:按官方文档描述,这种动态导入方式正尝试加入到ES的规范之中
- 创建async.js
export default function async() { console.log('异步引用'); } -
entry.js 加入代码
import('./async').then(async => { async.default(); }); // 等价于 /* require.ensure([], (require) => { const async = require('./async'); async.default(); }); */import()返回的是promise实例,所以我们还可以通过
Promise.all([import('./async')]).then(([async]) => {})的形式去引用多个模块;不过,当你需要兼容IE8-的浏览器时,你需要额外导入 promise-polyfill 。System.import()和import()方法作用相同,在本文撰写期间的2.5.x版本前者依然可以使用,但官方文档有指出这个方法不建议使用
- 创建async.js
-
修复ugulifyJS压缩css文件时误删除[dpr]问题:当然我们可以通过别的工具去代替
-
函数方式导出配置:可以通过参数来代替设置复杂的环境变量
- 修改 webpack.config.js, 并执行
webpack --env.devmodule.exports = function(env) { return { entry: './entry.js', output: { filename: 'bundle.js' }, // 新的“环境变量”使用方式 (此处新增了sourcemap) devtool: env.dev ? 'cheap-module-eval-source-map' : false }; };
- 修改 webpack.config.js, 并执行
- Tree shaking:去除无用代码,适用于文件目录结构复杂的项目,更多查看后文
配置“升级”
-
module.loaders-->modules.rules
使用loader时需要把loader名字写全,如style需要写为style-loader -
移除 module.preLoaders, module.postLoaders
现在通过
module.rules.enforce属性来配置 -
不再需要手动加入
DedupePlugin,OccurrenceOrderPlugin,json-loader,devServer.inline等配置毕竟几乎大家都需要用到它们
-
webpack-dev-server,extract-text-webpack-plugin,html-webpack-plugin这三个常用的工具必须升级到2.x版本,否则无法和webpack2作用 -
合并分散的resolve配置
resolve.root, resolve.fallback, resolve.modulesDirectories
通过配置好resolve.modules有助于提高定位引用文件的速度const path = require('path'); module.exports = function(env) { return { // ... resolve: { modules: [ path.resolve(__dirname, 'node_modules'), ], } }; };
下图为以前一次把个迷你项目从webpack1升级到webpack2的基本配置变更
了解TreeShaking
-
Tree shaking 示例
修改fn.js
// ... export function unused(){ document.write('I am an unused Function'); }修改entry.js
import fn, {unused} from './fn'; fn(); // ...执行
webpack --env(这里不使用env.dev来查看较为美观的打包代码)后,我们会发现生成的bundle代码中出现如下片段 此时再执行
webpack --optimize-minimize --env,打包的代码经过压缩处理后,unused()这个没有被调用的函数被彻底删掉了。
简单而然,webpack2 中的 tree shaking就是一个按需打包模块一种实现。但需要tree shaking生效,被引用的模块必须遵循es6模块导出的规范,详看后文。 -
Tree shaking 起源
在前端圈子中,该解释 “起源”于 rollup.js 作者。
Rollup中的 Tree-shaking 是无用代码移除(DCE, dead code elimination)的一种实现。利用AST(Abstract Syntax Tree,译作 抽象语法树),找到被使用的代码块然后注入到输出文件中。而Webpack2“原生”支持的ES6模块静态性引用,可以帮助标记编译后的多余代码,并在压缩时"甩掉"它们。
更多关于抽象语法树的理解可以通过 在线抽象语法树解释工具 去自行体验
-
ES6模块的静态性的作用:
- DCE
-
快速定位代码
-
使用Commonjs去引用库的时候,调用其子属性会触发对象属性查表,这会降低编译的效率
const lib = require('lib'); lib.someFunc(); // 属性查表 -
而import的静态特性使其跳过这个步骤;
import * as lib from 'lib'; lib.someFunc(); // 静态处理
-
-
提高变量校验效率
- 为macro(宏)做准备,现有macro库http://sweetjs.org/
-
Tree shaking 横向对比
babel-plugin-import是一个类tree shaking的babel插件,它能够把import { Button } from ‘antd’;这种代码转换为import Button ‘antd/lib/button’;的形式。- 优点在于
o 不硬性要求引用ES6模块
o 构建速度较快 - 缺点在于
x 需指定按需打包的模块
x 自己创建的模块使用不便
x 无法把同一个文件里的多个export分离
x 配置错误将会导致依赖丢失
如今的webpack2的tree shaking 主要适用范围如下
import {lastName} form 'name';-- named importimport name from 'name';-- default importimport * as all from 'name;
const name = require('name');如今并不是所有开源组件都提供ES6模块的代码,所以如果想最有效的去除多余代码,把 babel-plugin-import 和 webpack2 Tree shaking组合使用来打包压缩生产环境的代码为当下最优选择。
- 优点在于
-
Webpack2 和 Babel 组合的短暂演变
在使用webpack的同时,我们大多都需要使用到babel来支持转换ES6、ES7、TS等一系列语法糖,那一旦使用babel,务必要防止babel对import语法先行处理。为了达到这个目的,babel的配置也经历过比较明显的转变最终简单易懂:
1-2速度以及打包大小对比
该速度对比数据为同样代码每项执行5次后取最大时长的数据,代码如下:
import react from 'react'; // react15.5.4 不提供ES6模块
import {compose} from 'refux'; // redux3.6.0 提供ES6模块
速度
| webpack1 | webpack2 | |
|---|---|---|
| dev-server 启动服务 | 2187ms | 2252ms |
| dev-server 文件更改 | 41ms | 27ms |
| production | 1991ms | 2057ms |
打包大小
| webpack1 | webpack2 | |
|---|---|---|
| dev-server | 1.38MB | 1.75MB |
| production | 53.3kB | 48.5kB |
由此可见,在开发过程中,webpack2打包速度较快但需加载的代码文件大小较大;生产环境代码webpack2生成的文件体积更小(但这要求开发者遵循使用ES6模块的写法)
Webpack2优缺点汇总
个人最后总结的优缺点如下
- 优点
o change文件打包效率提高
o 升级快捷
o 加强code splitting时chunk文件的错误定位(这个真心棒)
o 官方文档更加清晰
o 和babel6完美契合 - 缺点
x 自带的tree shaking对非ES6模块和对象动态属性无效
x 动态import实现方式不标准,还需要 bable-plugin-syntax-dynamic-importx Chrome下devtool为cheap-module-source-map等时源码定 位有数行误差x 后文中的随着webpack2版本迭代,以上缺点正慢慢改正
结语
我想不到任何一个不升级的理由,毕竟这是正式版了。:) 如文中有与实际不对等的情况,务必告诉我好让我能撇除误解~~~
Issue
webpack2处理原生ES6 Module时, 无法使用babel-plugin-add-module-exports插件 。该插件能让babel6处理export时,如同babel5一样,生成语句 module.exports = exports["default"] ;webpack2中export default转换后为 __webpack_exports__["default"] 而非 exports["default"] ,故执行代码时会报错。
参考
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Remote
Jason Fried、David Heinemeier Hansson / Crown Business / 2013-10-29 / CAD 26.95
The “work from home” phenomenon is thoroughly explored in this illuminating new book from bestselling 37signals founders Fried and Hansson, who point to the surging trend of employees working from hom......一起来看看 《Remote》 这本书的介绍吧!