Webpack2 初识
栏目: JavaScript · 发布时间: 6年前
内容简介: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.dev
module.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"]
,故执行代码时会报错。
参考
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Java JDK6学习笔记
林信良 / 清华大学出版社 / 2007-4 / 59.90元
《Java JDK6学习笔记》是作者良葛格本人近几年来学习Java的心得笔记,结构按照作者的学习脉络依次展开,从什么是Java、如何配置Java开发环境、基本的Java语法到程序流程控制、管理类文件、异常处理、枚举类型、泛型、J2SE中标准的API等均进行了详细介绍。本书还安排了一个“文字编辑器”的专题制作。此外,Java SE6的新功能,对Java lang等套件的功能加强,以及JDBC4.0、......一起来看看 《Java JDK6学习笔记》 这本书的介绍吧!