webpack是一款模块加载器兼打包工具,它能把各种资源,例如JS(含JSX)、coffee、样式(含less/sass)、图片等都作为模块来使用和处理。
简单说就是模块加载器,通过使用Webpack,能够像Node.js一样处理依赖关系,然后解析出模块之间的依赖,将代码打包。
webpack主要特性如下:
Source map就是一个信息文件,里面储存着位置信息。也就是说,转换后的代码的每一个位置,所对应的转换前的位置。有了它,出错的时候,除错工具将直接显示原始代码,而不是转换后的代码,这将给开发者带来了很大方便。
详见传送门
首先得安装Node.js
//这是为了能够在全局环境中使用webpack命令
//非全局安装需使用node_modules/.bin/webpack
$ npm install webpack -g
$ npm install webpack --save-dev
$ webpack -v
{
"name": "demo",
"version": "1.0.0",
"description": "",
"scripts": {
"start": "webpack-dev-server --progress --colors --hot --inline -d",
"build": "webpack --progress --colors --minify"
},
"license": "ISC",
"dependencies": {
},
"devDependencies": {
}
}
执行类似于node_modules/.bin/webpack这样的命令不仅繁琐还容易出错,不过值得庆幸的是npm可以引导任务执行,对其进行配置后可以使用简单的npm start或者npm run build命令来代替这些繁琐的命令。在package.json中对npm的脚本部分进行相关设置即可,设置方法如上面的配置所示。
**注意:**npm的start是一个特殊的脚本名称,它的特殊性在于:在命令行中使用npm start就可以执行相关命令,如果对应的此脚本名称不是start,想要在命令行中运行时,需要这样用npm run {script name}如上面例子中的npm run build。
**特别说明:**package.json中的脚本部分已经默认在命令前添加了node_modules/.bin路径,所以无论是全局还是局部安装的Webpack,你都不需要写前面那指明详细的路径了。
每个项目下都必须配置有一个 webpack.config.js ,它的作用如同常规的 gulpfile.js/Gruntfile.js ,就是一个配置项,告诉 webpack 它需要做什么。
webpack.config.js配置详解
这里给出我自己的配置:
var webpack = require('webpack');
var commonsPlugin = new webpack.optimize.CommonsChunkPlugin('common.js');
module.exports = {
noParse:[/jquery/],//表示跳过jquery,不对其进行编译,这样可以提高打包的速度
plugins:[
commonsPlugin,
//配置了NoErrorsPlugin插件,用来跳过编译时出错的代码并记录,使编译后运行时的包不会发生错误
new webpack.NoErrorsPlugin()
],
entry: {
index:'./src/js/startup.js'
},
//入口文件输出配置
output:{
//path: 打包好的资源存放的位置
path:'./js',
//filename: 打包后的文件名
filename: '[name].bundle.js'
},
// externals: { //排除构建文件外
// 'react': 'React'
// },
module: {
//加载器配置
//module.loaders 是最关键的一块配置。它告知 webpack 每一种文件都需要使用什么加载器来处理
loaders:[
{
//用于匹配加载器支持的文件格式的正则表达式
test: /\.css$/,
//多个加载器通过"!"连接,加载器是从右向左开始使用的
//loader指定了要使用的加载器类型
loader: 'style-loader!css-loader'
},
{
//配置信息的参数“?limit=8192”表示将所有小于8kb的图片都转为base64形式 (其实应该说超过8kb的才使用 url-loader 来映射到文件,否则转为data url形式)
test: /\.(png|jpg)$/,
//加载器支持通过查询字符串的方式接收参数
loader: 'url-loader?limit=8192'
},
{
//presets:指定哪些代码转换器将启用babel
test: /\.js$/,
loader: 'babel-loader',
//exclude:/node_modules/,排除node_modules这个文件夹中的代码
//include:/(admin|consumer)//表示只针对这两个文件夹中的代码进行打包
//include/exclude:手动添加必须处理的文件(文件夹)或屏蔽不需要处理的文件(文件夹)
exclude:/node_modules/,
query:{
presets:['es2015','react']
}
},
{
test: /\.jsx$/,
//?表示加载器支持通过查询字符串的方式接收参数
//!表示多个加载器之间通过"!"连接
loader: 'babel-loader!jsx-loader?harmony'
}
]
},
//文件解析配置
//会依次寻找不带后缀的文件,.js后缀文件以及.jsx后缀文件。先找到哪个是哪个
resolve: {
extensions: ['', '.js', '.jsx'],//当requrie的模块找不到时,添加这些后缀
root:'E:/myev/src',//绝对路径
alias: {//别名配置
}
}
}
}
这里对Webpack的打包行为做了配置,主要分为几个部分:
jquery:path.resolve(__dirname,'./bower_components/jquery/dist/jquery.js')
,
这样在 import 时可以替换引用路径。
- module:定义了对模块的处理逻辑,这里可以用loaders定义了一系列的加载器,以及一些正则。当需要加载的文件匹配test的正则时,就会调用后面的loader对文件进行处理,这正是webpack强大的原因。比如这里定义了凡是.js结尾的文件都是用babel-loader做处理,而.jsx结尾的文件会先经过babel-loader处理,然后经过jsx-loader处理。当然这些loader也需要通过npm install安装,“-loader”其实是可以省略不写的,多个loader之间用“!”连接起来。
Webpack还有很多其他的配置,具体可以参照它的配置文档
对应各种不同文件类型的资源, Webpack 有对应的模块 loader。比如 CoffeeScript 用的是 coffee-loader, 其他还有很多。请参考相关文档
在 Webpack 当中, 所有的资源都被当作是模块, js, css, 图片等等。因此, Webpack 当中 js 可以引用 css, css 中可以嵌入图片 dataUrl。
Webpack的加载器支持参数,jsx-loader就可以添加?harmony参数使其支持ES6语法。为了让Webpack识别什么样的资源应该用什么加载器去载入,需要在配置文件进行配置:通过正则表达式对文件名进行匹配。
加载器之间的级联是通过感叹号来连接,例如对于LESS资源,写法为style-loader!css-loader!less-loader。从右向左开始使用,less->转为css字符串->使用style将代码放到页面style标签中。
css-loader——将样式打包成字符串
style-load——将样式字符串添加到页面的style标签中
对于小型的图片资源,也可以将其进行统一打包,由url-loader实现,代码中url-loader?limit=8192含义就是对于所有小于8192字节的图片资源也进行打包。这在一定程度上可以替代Css Sprites方案,用于减少对于小图片资源的HTTP请求数量。
如果通过npm install -g webpack方式安装webpack的话,可以通过命令行直接执行打包命令,比如:
$ webpack –config webpack.config.js
这样就会读取当前目录下的webpack.config.js作为配置文件执行打包操作
常用webpack命令:
在开发环境构建一次
webpack
构建并生成源代码映射文件
webpack -d
在生成环境构建,压缩、混淆代码,并移除无用代码
webpack -p
快速增量构建,可以和其他选项一起使用
webpack –watch
progress 显示打包过程中的进度,colors打包信息带有颜色显示
webpack –progress –colors
require(‘lodash’) // 从模块目录查找
require(‘./file’) // 按相对路径查找
require(‘./bootstrap.css’);
require(‘./myapp.less’);
var img = document.createElement(‘img’);
img.src = require(‘./glyph.png’);
一个模块需要用它的文件路径来加载,看一下下面的这个结构:
–app
——modules
———–MyModule.js
——main.js (entry point,入口文件)
——utils.js
打开 main.js 然后可以通过下面两种方式引入 app/modules/MyModule.js
app/main.js
// ES6
import MyModule from ‘./modules/MyModule.js’;
// CommonJS
var MyModule = require(‘./modules/MyModule.js’);
最开始的 ./ 是 “相对当前文件路径”
让我们打开 MyModule.js 然后引入 app/utils:
app/modules/MyModule.js
// ES6 相对路径
import utils from ‘./../utils.js’;
// ES6 绝对路径
import utils from ‘/utils.js’;
// CommonJS 相对路径
var utils = require(‘./../utils.js’);
// CommonJS 绝对路径
var utils = require(‘/utils.js’);
相对路径是相对当前目录。绝对路径是相对入口文件,这个案例中是 main.js。
Common Chunks 插件的作用:提取代码中的公共模块,然后将公共模块打包到一个独立的文件中去,以便在其它的入口和模块中使用。
我们在配置项中添加CommonChunksLoader的配置,使用它来提取公共模块。
var webpack = require('webpack');
var config = {
entry:{
main1:'./main1',
main2:'./main2'
},
output:{
filename:'bundle.[name].js'
},
plugins: [
new webpack.optimize.CommonsChunkPlugin('common.js', ['main1', 'main2'])
]
};
module.exports = config;
在配置文件中添加了webpack的引用(同时也要在项目目录下安装webpack),然后添加了plugins选项,引用了webpack.optimize.CommonsChunkPlugin来提取公共模块,参数common.js表示公共模块的文件名,后面的数组元素与entry一一对应,表示要提取这些模块中的公共模块。
重新使用webpack打包后,看到生成的文件中多了一个common.js
这个common.js正是公共部分a和b两个模块。而生成的bundle.main1.js中只包含了c模块,bundle.main2.js中则没有包含任何其它模块。
具体代码详见我的github:传送门
最后要在HTML文件中引入公共部分common.js。
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>CommonsChunkPlugintitle>
head>
<body>
<script type="text/javascript" src="common.js">script>
<script type="text/javascript" src="bundle.main1.js">script>
body>
html>
OccurenceOrderPlugin:给经常使用的模块分配最小长度的id,这样可以减少文件大小。
HotModuleReplacementPlugin:是热替换,热替换和dev-server的hot有什么区别?不用刷新页面,可用于生产环境。
NoErrorsPlugin:在打包时不会因为错误而中断
ProvidePlugin: 定义一些在import时能自动引入的变量,如定义了 $: 'jquery'
后,可以在文件中直接使用$
,webpack可以自动帮你加上 var $ = require('jquery')
。
DllPlugin: 将一些模块预编译,类似windows里的dll,可以在项目中直接使用,无需再构建。注意要在output中指定 library ,并在DllPlugin中指定与其一致的 name ,在有多个入口时可以使用 [name] 和 [hash] 来区分,因为这个参数是要赋值到global上的,所以这里使用 [hash] 不容易出现变量名冲突的情况。
DllReferencePlugin: 引用之前打包好的dll文件,注意下context参数,这个应该根据manifest.json文件中的引用情况来赋值,如果引用的都是npm安装的库,这里就填项目根目录就好了。
DefinePlugin: 可以定义编译时的全局变量,有很多库(React, Vue等)会根据 NODE_ENV 这个变量来判断当前环境。为了尽可能减少包大小,在生产环境中要定义其为 JSON.stringify(“production”)
optimize.UglifyJsPlugin: 配置压缩代码。
optimize.DedupePlugin: 可以减少重复文件数。
ExtractTextPlugin: 可以将所有css文件打包到一个css文件中。
Webpack有一个非常好用的功能叫做热替换(Hot-replace),尤其是结合React Hot Loader插件,开发过程中都不需要刷新浏览器,任何前端代码的更改都会实时的在浏览器中表现出来。
需要安装Webpack-dev-server,一个轻量的node.js express服务器。
npm install webpack-dev-server --save-dev
webpack-dev-server有两种模式支持自动刷新——iframe模式和inline模式。
注意:
iframe模式下:页面是嵌套在一个iframe下的**,在代码发生改变的时候,这个iframe会重新加载;
使用iframe模式无需额外的配置,只需在浏览器输入
http://localhost:8080/webpack-dev-server/index.html
在inline模式下:一个小型的webpack-dev-server客户端会作为入口文件打包,这个客户端会在后端代码改变的时候刷新页面。
使用inline模式有两种方式:命令行方式和Node.js API。
命令行方式比较简单,只需加入–line选项即可。例如:
webpack-dev-server --inline
使用–inline选项会自动把webpack-dev-server客户端加到webpack的入口文件配置中。
其他相关参数介绍:
webpack-dev-server --progress --colors --hot --inline -p -d;
–progress 显示打包进度
–colors配置打包输出颜色显示
–hot热加载,代码修改完后自动刷新
–inline 是刷新后的代码自动注入到打包后的文件中(当源文件改变时会自动刷新页面)
-d 是debug模式,输入一个source-map,并且可以看到每一个打包的文件
-p 是对代码进行压缩
参考博文:
WebPack 简明学习教程
WebPack 常用功能介绍
Webpack 指南
关于简聊 Webpack 配置的一些注释
Webpack-dev-server结合后端服务器的热替换配置
WEBPACK DEV SERVER
webpack和webpack-dev-server配置的个人小结
webpack使用优化
入门 Webpack,看这篇就够了