前言
webpack是目前前端开发必不可少的一款模块加载器兼构建工具,它能极其方便的处理各种资源的打包和使用, 让前端开发获得与后端开发几乎一致的体验。
Webpack是什么
CommonJS 和 AMD 是用于 JavaScript 模块管理的两大规范,前者定义的是模块的同步加载,主要用于NodeJS;而后者则是异步加载,通过 requirejs 等工具适用于前端。随着 npm 成为主流的 JavaScript 组件发布平台,越来越多的前端项目也依赖于 npm 上的项目,或者自身就会发布到 npm 平台。因此,让前端项目更方便的使用 npm 上的资源成为一大需求。
web开发中常用到的静态资源主要有JavaScript、CSS、图片、Jade等文件,webpack中将静态资源文件称之为模块。webpack是一个module bundler(模块打包工具),其可以兼容多种js书写规范,且可以处理模块间的依赖关系,具有更强大的js模块化的功能。Webpack对它们进行统一的管理以及打包发布,其官方主页用下面这张图来说明Webpack的作用:
Webpack的核心原理
Webpack的两个最核心的原理分别是:
1.一切皆模块
正如js文件可以是一个“模块(module)”一样,其他的(如css、image或html)文件也可视作模 块。因此,你可以require(‘myJSfile.js’)亦可以require(‘myCSSfile.css’)。这意味着我们可以将事物(业务)分割成更小的易于管理的片段,从而达到重复利用等的目的。
2.按需加载
传统的模块打包工具(module bundlers)最终将所有的模块编译生成一个庞大的bundle.js文件。但是在真实的app里边,“bundle.js”文件可能有10M到15M之大可能会导致应用一直处于加载中状态。因此Webpack使用许多特性来分割代码然后生成多个“bundle”文件,而且异步加载部分代码以实现按需加载。
Webpack特点
- 对 CommonJS 、 AMD 、ES6的语法做了兼容
- 对js、css、图片等资源文件都支持打包
- 串联式模块加载器以及插件机制,让其具有更好的灵活性和扩展性,例如提供对CoffeeScript、ES6的支持
- 有独立的配置文件webpack.config.js
- 可以将代码切割成不同的chunk,实现按需加载,降低了初始化时间
- 支持 SourceUrls 和 SourceMaps,易于调试
- 具有强大的Plugin接口,大多是内部插件,使用起来比较灵活
- webpack 使用异步 IO 并具有多级缓存。这使得 webpack 很快且在增量编译上更加快
Webpack安装和配置
安装
webpack 可以作为全局的 npm 模块安装,也可以在当前项目中安装。
1 | npm install -g webpack //全局安装 |
对于全局安装的webpack,直接执行此命令会默认使用当前目录的webpack.config.js作为配置文件。如果要指定另外的配置文件,可以执行:
1 | webpack —config webpack.custom.config.js |
配置
每个项目下都必须配置有一个 webpack.config.js ,它的作用如同常规的 gulpfile.js/Gruntfile.js ,就是一个配置项,告诉 webpack 它需要做什么。
webpack.config.js文件通常放在项目的根目录中,它本身也是一个标准的Commonjs规范的模块。在导出的配置对象中有几个关键的参数:
entry
entry 参数定义了打包后的入口文件,可以是个字符串或数组或者是对象;如果是数组,数组中的所有文件会打包生成一个filename文件;如果是对象,可以将不同的文件构建成不同的文件:
1 | { |
ps: chunk:被entry所依赖的额外的代码块,同样可以包含一个或者多个文件
该段代码最终会生成一个 page1.bundle.js 和 page2.bundle.js,并存放到 ./dist/js/page 文件夹下
output
output参数是个对象,定义了输出文件的位置及名字:
1 | output: { |
path: 打包文件存放的绝对路径
publicPath: 网站运行时的访问路径
filename:打包后的文件名
当我们在entry中定义构建多个文件时,filename可以对应的更改为[name].js用于定义不同文件构建后的名字。
module
在webpack中JavaScript,CSS,LESS,TypeScript,JSX,CoffeeScript,图片等静态文件都是模块,不同模块的加载是通过模块加载器(webpack-loader)来统一管理的。loaders之间是可以串联的,一个加载器的输出可以作为下一个加载器的输入,最终返回到JavaScript上:
1 | module: { |
注意
webpack 2.x 之后 module.loaders改成了module.rules
webpack1.x中loaders可以链式调用,在2.x中使用rule.use配置项替换
取消在模块中自动添加-loader后缀
resolve
webpack在构建包的时候会按目录的进行文件的查找,resolve属性中的extensions数组中用于配置程序可以自行补全哪些文件后缀:
1 | resolve: { |
然后我们想要加载一个js文件时,只要 require(‘common’)就可以加载common.js文件了。
注意一下, extensions 第一个是空字符串 ! 对应不需要后缀的情况.
plugin
webpack提供了[丰富的组件]用来满足不同的需求,当然我们也可以自行实现一个组件来满足自己的需求:
1 | plugins: [ |
在webpack中编写js文件时,可以通过require的方式引入其他的静态资源,可通过loader对文件自动解析并打包文件。通常会将js文件打包合并,css文件会在页面的header中嵌入style的方式载入页面。但开发过程中我们并不想将样式打在脚本中,最好可以独立生成css文件,以外链的形式加载。这时extract-text-webpack-plugin插件可以帮我们达到想要的效果。需要使用npm的方式加载插件,然后参见下面的配置,就可以将js中的css文件提取,并以指定的文件名来进行加载。
1 | npm install extract-text-webpack-plugin –save-dev |
1 | plugins: [ |
externals
防止将某些 import 的包(package)打包到 bundle 中,而是在运行时(runtime)再去从外部获取这些扩展依赖(external dependencies)。
例如,从 CDN 引入 jQuery,而不是把它打包:
1 | <script src="https://code.jquery.com/jquery-3.1.0.js" |
1 | externals: { |
这样就剥离了那些不需要改动的依赖模块,换句话,下面展示的代码还可以正常运行:
1 | import $ from 'jquery'; |
关于 webpack.config.js 更详尽的配置可以参考 这里
Webpack常用命令
webpack的使用通常有三种方式:
1、命令行使用:webpack 其中entry.js是入口文件,result.js是打包后的输出文件
2、node.js API使用:
1 | var webpack = require('webpack'); |
3、默认使用当前目录的 webpack.config.js 作为配置文件。如果要指定另外的配置文件,可以执行:webpack –config webpack.custom.config.js
webpack 的执行也很简单,直接执行
1 | webpack --display-error-details |
常用命令
webpack的使用和browserify有些类似,下面列举几个常用命令:
webpack 最基本的启动webpack命令
webpack -w 提供watch方法,实时进行打包更新
webpack -p 对打包后的文件进行压缩
webpack -d 提供SourceMaps,方便调试
webpack –colors 输出结果带彩色,比如:会用红色显示耗时较长的步骤
webpack –profile 输出性能数据,可以看到每一步的耗时
webpack –display-modules 默认情况下 node_modules 下的模块会被隐藏,加上这个参数可以显示这些被隐藏的模块
参考资料:
webpack
webpack中文文档
【翻译向】webpack2 指南(上)
【翻译向】webpack2 指南(中)
【翻译向】webpack2 指南(下)
今天,你升级Webpack2了吗?
webpack使用小记
Webpack 2 有哪些新东西
webpack2 终极优化
基于webpack搭建前端工程解决方案探索
webpack入门
webpack使用优化(基本篇
webPack 参考
webpack打包bundle.js体积大小优化
开发工具心得:如何 10 倍提高你的 Webpack 构建效率
详解前端模块化工具-Webpack
webpack 多页面构建
使用Webpack打包时的“多页”实践
Webpack2.x踩坑与总结
Webpack——令人困惑的地方