不得不说,webpack
配置确实烦琐了一些,很多人都使用gulp
的插件gulp-webpack
来做其他事情。
配置webpack
webpack的构建过程需要一个配置文件,一个典型的配置文件webpack.config.js
大概就是这样
var webpack = require('webpack');
module.exports = {
// 配置项
};
基本配置项
entry
module.exports = {
entry:'./example1.1',
output:{
filename:'bundle1.1.js'
}
};
我们也会碰到支持多个入口文件(entry)的情况,每一个入口都需要有自己的名字,具体对应entry的写法而言,有如下几种情况:
entry:'./example2.1'
// 或者
entry:['./example2.1','./example2.2']
//或者
entry:{
'example2.1':'example2.1.js',
'example2.2':'example2.2.js'
}
第三种是比较推荐的写法,这种写法中,名字和模块文件名一一对应,每个模块都有独立的名字。也就是output.filename
中的[name]
output
output.filename
output.filename
除了可以指定具体的文件名以外,还可以使用一些占位符,包括:
- name 模块名称
- hash 模块编译后的(整体)Hash值
- chunkhash 分片的Hash值
[name]
在上面的entry
中,前两种写法,模块是没有名字的,webpack会使用main作为模块名字,因此用数组来指定入口的情况,模块名会重复,而此时webpack会将它们的代码合并打包!而第三种写法,这里的[name]可以理解成模块名字。
[hash]与[chunkhash]
事实上,在webpack的文档中,这个name是指“chunk name”,即分片的名字,这里需要先剧透一下后面要说的“分片”的概念。所谓分片就是指一个入口模块的代码有可能会被分成多个文件,还有一些文件可能是来自模块的公共代码,而不是入口模块。因此这里的[name]并非严格与入口模块一一对应。
了解了这些情况之后,[hash]和[chunkhash]就自然好理解了,一个是指本次打包相关的整体的hash,一个是指分片的hash。
module.exports = {
entry:{
'example3.1':'./example3.1',
'example3.2':'./example3.2'
},
output:{
//这里分别用hash和chunkhash,结果不一样
filename:'[name]-[hash].js'
//filename:'[name]-[chunkhash].js'
}
};
output.path
output.path
来指定输出路径
output.path
也可以使用占位符。
如果想保持打包前源文件的目录结构,需要把目录写到模块名上,如:
entry:{
'example4.1':'./src/example4.1',
'hello/example4.2':'./src/hello/example4.2'
},
output:{
filename:'[name].js',
path:'./dist'
}
注意这里的filename
一定要包含[name]
才行,因为路径信息是带在模块名上的。
CommonChunks插件
Common Chunks
插件的作用就是提取代码中的公共模块,然后将公共模块打包到一个独立的文件中去,以便在其它的入口和模块中使用。
var webpack = require('webpack');
module.exports = {
entry:{
main1:'./main',
main2:'./main.2'
},
output:{
filename:'bundle.[name].js'
},
plugins: [
new webpack.optimize.CommonsChunkPlugin('common.js', ['main1', 'main2'])
]
};
参数common.js
表示公共模块的文件名,后面的数组元素与entry
一一对应,表示要提取这些模块中的公共模块。
但是,要记得在HTML中加入公共部分common.js
但模块化不应该有多个入口文件,入口文件不应时时改变,应在内部处理
使用loader
loader是webpack中一个重要的概念,它是指用来将一段代码转换成另一段代码的webpack插件
虽然本质上说,loader也是插件,但因为webpack的体系中还有一个专门的名词就叫插件(plguin),为避免混淆,后面不再将loader与插件混淆说,后文中这将是两个相互独立的概念。
loader的使用有三种方法,分别是:
- 在require中显式指定
- 在配置项(webpack.config.js)中指定
- 在命令行中指定
第二种,在配置项中指定是最灵活的方式,它的指定方式是这样:
module: {
// loaders是一个数组,每个元素都用来指定loader
loaders: [{
test: /\.jade$/, //test值为正则表达式,当文件路径匹配时启用
loader: 'jade', //指定使用什么loader,可以用字符串,也可以用数组
exclude: /node_modules/, //可以使用exclude来排除一部分文件
// exclude: /regexp/
include: 'dist', // 用来指定包含的文件
//可以使用query来指定参数,也可以在loader中用和require一样的用法指定参数,如`jade?p1=1`
query: {
p1:'1'
}
},
{
test: /\.css$/,
loader: 'style!css' //loader可以和require用法一样串联
},
{
test: /\.css$/,
loaders: ['style', 'css'] //也可以用数组指定loader
}]
}
串联
loader是可以串联使用的,也就是说,一个文件可以先经过A-loader再经过B-loader最后再经过C-loader处理。
require('style!css!./style.css');
参数
loader还可以接受参数,不同的参数可以让loader有不同的行为(前提是loader确实支持不同的行为),具体每个loader支持什么样的参数可以参考loader的文档。
参数的指定方式和url
很像,要通过?
来指定,例如指定literate
参数需要这样写:
require('coffee?literate=1!./a.coffee');
具体的可以对照官方的loader列表一一查看。