module: {
rules: [
{
test: /\.css$/,
use: ['style-loader','css-loader?minimize']
}
]
}
一、入门
loader可以看作是翻译员,配置module.rules数组里的规则,告诉webpack遇到哪些文件使用哪些loader去加载和转换。
如上的话就是告诉webpack当遇到.css文件后先采用css-loader,再由style-loader将css的内容注入javascript里,是由后往前的。
每个loader都可以通过URL querystring的方式传入参数,'css-loader?minimize'就是告诉css-loader要开启css压缩。
其中向loader传入的属性可以通过querystring实现,还可以通过Object实现。
use: [
'style-loader',
{
loader: 'css-loader',
options: {
minimize: true }
}
]
除了在webpack.config.js配置文件中配置loader,还可以在代码中指定用什么loader处理文件。例如
require (’style-loader! css-loader?minimize! ./main.css ’);
这样就能指定对./main.css这个文件先采用css-loader再采用style-loader进行转换。
module: {
rules: [
{
test: /\.css$/,
loaders: ExtractTextPlugin.extract({
use: ['css-loader']
})
}
]
},
plugin
是用来扩展webpack功能的。
extract-text-webpack-plugin就是用来提取css文件,使之不适用style的方式放在dom元素上、
DevServer是启动http服务器监听在8080端口,这时不会再./dist下面生成静态文件,原因是devServer会把构建的文件保存在内存中,需要通过http访问,由于DevServer不会理会webpack.config.js里配置的output.path属性,所以要获取bundle.js正确的url是http://localhost:8080/bundle.js,在index.html中就是src="bundle.js"
实时预览:修改main.js、main.css、show.js中任意的文件,保存会发现浏览器热更新。
webpack在启动时开启监听模式,会监听本地文件系统的变化,在发生变化时重新进行构建,然后通知DevServer,DevServer会让webpack在构建出的javascript代码里注入一个代理客户端用于控制网页,网页和devserver质检通过websocket协议通信,以方便devserver制度当向客户端发送命令。
修改index.html不会触发热更新,因为webpack启动时会以配置里entry为入口区递归解析出entry所依赖的文件,只有entry本身和依赖的文件才会被监听。
source map
在浏览器中运行的都是编译后的代码,可读性很差,如果遇到不知原因的bug,则需要打断点调试。调试工具可以通过source map映射代码,让我们在源代码上断点调试。
webpack的几个核心概念:
entry: webpack执行构建的第一步从entry开始。
module: 模块,在webpack里一切皆模块,一个模块对应一个文件。
chunk: 代码块,一个chunk由多个模块组合而成,用于代码合并和分割
loader: 模块转换器,用于将模块的原内容按照需求转换成新内容。
plugin: 扩展插件
output: 输出结果
resolve: 配置寻找模块的规则
DevServer: 配置DevServer
webpack在启动后会从entry里配置的module开始,递归解析entry依赖的所有module,没找到一个module,就会根据配置的loader去找对应的转换规则,对module进行转换后,再解析出当前module依赖的module。这些模块会以entry为单位进行分组,一个entry及其所有的依赖的module被分到一个组也就是一个chunk。最后webpack会将所有的chunk转换成文件输出。
二、配置
entry: 配置入口, webpack构建的起点,entry配置必填,不填或填错会报错。
entry类型可以是以下三种中的一种或者相互组合:
类型例子含义
string'./app/entry'入口模块的文件路径,可以是相对路径
array['./app/entry1','./app/entry2']入口模块的文件路径,可以是相对路径
object{a:'./app/entry-a',b:['./app/entry-b1','./app/entry-b2']配置多个入口,每个入口生成一个chunk
如果是array类型,在搭配output.library配置项使用时,只有数组里的最后一个入口文件的模块会被导出。
chunk的名称:
webpack会为每个生成的chunk去一个名称,chunk的名称和entry的配置有关。
如果entry是一个string或array,就只会生成一个chunk,这时chunk的名称是main
如果entry是一个object,就可能出现多个chunk,这时chunk的名称是object键值对中键的名称。
配置动态的entry
加入项目里有很多个页面需要为每个页面的入口配置一个entry,但是这些页面爽可能会剬增长,这时entry不能写成静态的值,其解决办法是将entry设置成一个动态函数返回上面所说的配置。
entry: () => {
return {
a: '/pages/a',
b: 'pages/b'
}
}
entry: () => {
returnnewPromise((resolve) => {
resolve({
a: '/pages/a',
b: 'pages/b' })
})
}
context:
webpack在寻找相对路径的文件时会以context为根目录,context默认执行启动webpack时所在的当前工作目录。若想改变context的默认配置,可以这样设置:
context: path.resolve(__dirname, 'app')
注意:context必须是一个绝对路径的字符串。
除此之外还可通过在启动webpack时带上参数webpack --context 来设置context。
Output:
output配置如何输出最终想要的代码。output是一个对象,里面包含很多配置项:
filename: 配置输出文件名,string类型,如果只输出一个文件,则可以将它写成静态不变的。但是如果有多个chunk要输出时,就需要借助模板和变量了。
filename: '[name].js'
代码里的[name]代表用内置的name变量替换[name],这时我们可以将它看做一个字符串模块函数,每个要输出的chunk都会通过这个函数去拼接输出的文件名称。
内置变量列表:
变量名含义
idchunk唯一标识,从0开始
namechunk名称
hashchunk唯一标识的hash值
chunkhashchunk内容的hash值
其中,hash和chunkhash的长度是可以指定的, [hash:8]代表8位hash值,默认是20位。
注意: ExtractTextPlugin插件使用contenthash二不是chunkhash来代表哈希值,原因在于ExtractTextPlugin提取出来的内容是代码本身,而不是一组模块组成的chunk。
chunkFilename: 配置无入口的chunk在输出时的文件的名称,和filename非常类似,反chunkFilename只用于指定在运行过程中生成的chunk在输出时的文件名称。会在运行时生成chunk的常见场景包括:使用commonchunkplugin使用import('path/to/module')动态加载等。
path: 配置输出文件存放的本地目录,必须是string类型的绝对路径。通常用__diename去获取:path: path.resolve(__dirname, 'dist_[hash]')
publicPath: 在复杂的项目里可能会有一些构建出的资源需要异步加载,加载这些异步资源需要对应的URL地址。
crossOriginLoading: webpack输出的部分代码可能需异步加载,而异步加载时通过JSONP方式实现的,JSONP的原理是动态向HTML插入一个标签去加载异步资源。crossOriginLoading则是配置这个异步插入的标签的crossorigin值。
script标签的crossorign属性可以取以下值:
anonymous(默认),在加载此脚本资源时不会带上用户的cookies
use-credentials: 带上用户的cookie,
通常用来获取异步加载的脚本执行时的详细错误信息。
libraryTarget和library
当webpack去构建一个可以被其他模块导入的库时,则需要libraryTarget和library。
libraryTarget配置以何种方式导出库
library配置导出库的名称
libraryTarget是字符串的枚举类型,支持以下配置:
1. var (默认),编写的库将通过var被赋值给通过library指定的名称的变量。
2.commonjs, 编写的库通过CommonJS规范导出
3.commonjs2, 编写的库通过CommonJS2规范导出
4.this, 编写的库通过this被赋值给通过library指定的名称
5. window,编写的库通过this被赋值给通过window指定的名称
6. global,编写的库通过this被赋值给通过global指定的名称
libraryExport
配置要导出的模块中哪些子模块需要被导出,只有在libraryTarget被设置成commonjs或者commonjs2时使用才有意义。
Module
配置处理模块的规则。
配置loader
rules
配置模块的读取和解析规则,通常用来噢诶之loader,其类型是一个数组,数组里每一项都描述了如何处理部分文件。配置一项rules大致可通过以下方式爱完成。
条件匹配: 通过test、include、exclude三个配置项来选中loader要应用规则的文件。
应用规则: 通过use配置项来应用loader,可以只应用一个loader或者按照从后往前的顺序应用一组loader,同时可分别向loader传入参数
重置顺序: 一组loader的执行顺序默认是从右到左执行的,通过enforce选项可以将其中一个loader的执行顺序放到最前或最后
module: { rules: [
{
//命中javascript文件test: /\.js$/,
//用babel-loader转换javascript文件//?cacheDirectory表示传给babel-loader的参数,用于缓存babel的编译结果,加快重新编译的速度use: ['babel-loader?cacheDirectory'],
//只命中src目录里的javascript文件,加快webpack搜索速度include: path.resolve(__dirname, 'src')
},
{
//命中scss文件test: /\.scss$/,
//使用一组loader去处理scss文件//处理顺序从后到前,先交给sass-loader处理,再将结果交给css-loader,最后交给style-loaderuse: ['style-loader','css-loader','sass-loader'],
//排除node_modules目录下的文件exclude: path.resolve(__dirname, 'node_modules')
},
{
//对非文本采用file-loader加载test: /\.(gif|png|jpe?g|eot|woff|ttf|svg|pdf)$/,
use: ['file-loader'],
},
//在loader需要传入很多参数时,我们还可以通过一个Object来描述,例如在上面的babel-loader配置中有如下代码 {
use: [
{
loader: 'babel-loader',
options: {
cacheDirectory: true },
//enforce: 'post'的含义是将该loader的执行顺序放到最后//enforce: 'pre'的含义是将该loader的执行顺序放到最前enforce: 'pre' },
//省略其余的loader ]
},
//test也支持数组类型 {
test: [/\.jsx?$/,/\.tsx?$/]
}
]
}
noParse
这个配置项可以让webpack忽略对部分没采用模块化的文件的递归解析和处理,这样做的好处是能提高构建性能,原因是一些库如jquery,chartjs庞大又诶呦采用模块化标准,让webpack去解析这些文件耗时又没有意义。
noParse是可选配置项,类型需要 RegExp、[RegExp]、function中的一种。例如,忽略jquery,chartjs:
//正则noParse:/jquery|chartjs/,
//使用函数,webpack3.0.0后支持noParse: (content) => {
//content代表一个模块的路径return/jquery|chartjs/.test(content);
}
parser
因为webpack是以模块化的javascript文件为入口的,所以内置了对模块化javascript的解析功能,支持AMD、CommonJS,SystemJS,ES6。parser属性可以更细粒的配置那些模块预发被解析,哪些不被解析。parser可以精确到语法层面。
test: /\.js$/ use: [ ’babel-loader’],
parser: {
amd: false //禁用AMD
commonjs : false , //禁用CommonJS
system : false, //禁用SystemJS
harmony: false//禁用ES6 import/exportrequireinclude: false //禁用require.include
requireEnsure: false //禁用require.ensure
requireContext: false //禁用require.context
browserify: false, //禁用browserfiry
requireJs :false, //禁用requirejs
Resolve
webpack在启动后会从配置的入口模块触发找出所有依赖的模块,resolve配置webpack如何寻找模块所对应的文件。webpack内置javascript模块化预发解析功能,默认会采用模块化标准里约定的规则去寻找。也可以根据自己的需要修改默认的规则。
alias
resolve.alias配置项通过别名来将路径映射成一个新的导入路径。
resolve: {
alias: {
components: './src/components'
}
}
当通过import Button from 'components/button' 导入时,时间上被alias等价替换成了import Button from './src/components/button'。
alias配置的含义是,将导入的语句里的components关键字替换成./src/components/。
alias还支持通过$符号来缩小范围到只命中以关键字结尾的导入语句:
resolve: {
alias: {
'react$': '/path/to/react.min.js'
}
}
react$只会命中以react结尾的导入语句,即只会将import 'react'关键字替换成 import '/path/to/react.min.js'
mainFields
有些第三方模块会针对不同的环境提供几份代码。webpack会根据mainFields的配置去决定优先采用哪部分代码。
mainFields: ['browser', 'main'] 默认
extensions
导入语句没带文件后缀时,webpack会自动带上后缀去尝试访问文件是否存在。
extensions用于配置尝试过程中用到的后缀列表,默认是:
extensions: ['.js', '.json']。比如如果我们要优先选择TypeScript文件,则可以这样配置: extensions : ['.ts', '.js', '.json']
modules
resolve.modules配置webpack去哪些目录下寻找第三方模块,默认只会去node_modules目录下寻找。比如被大量导入的模块都在./src/components目录下,则将modules配置成modules: ['./src/components'. 'node_modules']后,则可以简单的使用import 'button'导入
descriptionFiles
配置描述第三方模块的文件名称,也就是package.json文件。默认descriptionFiles: ['package.json']
enforceExtension
如果配置为true,所有导入语句必须带文件后缀名,不然会报错。
enforceModuleExtension
和enforceExtension作用相似,只对node_modules下的模块生效。通常配合enforceExtension使用,因为配置enforceExtension:true后,第三方模块的大多数导入语句都没有后缀,此时配置enforceModuleExtension:false来兼容。
Plugin
plugin用于扩展webpack功能。
plugins配置项接收一个数组,数组的每一项都是一个呀使用的plugin实例,plugin需要的参数通过构造函数传入。
DevServer
hot
配置是否启用热替换功能,默认行为是在发现源代码被更新后通过自动刷新整个页面来做到实时预览,开启热替换功能后,将在不刷新整个页面的情况下通过用新模块替换老模块来做到实时预览。
inline
配置是否将这个代理客户端自动注入将运行在页面中的chunk里,默认自动注入。
· 开启inline,devserver会在构建变化后的代码时通过代理客户端控制网页刷新
· 如果关闭inine,devserver无法直接控制要开发的网页,通过iframe方式去运行开发的网页。代码变化去刷新iframe,这时需要去http://localhost:8080/webpack-dev-server/实时预览网页
最方便的方法是开启inline
historyApiFallback
用于方便开发html5 history api的单页应用。这类单页应用要求服务器在针对任何命中的路由时,都返回一个对应的index.html文件。
最简单的做法是:
historyApiFallback: true
这会导致任何请求都会返回index.html文件。
如果我们的应用由多个单页应用组成,则需要devserver根据不同的请求返回不同的html文件,配置如下:
historyApiFallback: {
rewrites: [
//user开头返回的是user.html{from: /^\/user/, to: '/user.html'},
{from: /^\/user/, to: '/game.html'}
]
}
contentBase
配置devserver http服务器文件根目录。在默认情况下为当前的执行目录,通常是项目根目录,一般不用设置它。
headers
可以在http响应中注入一些http响应头。
host
配置devserver服务监听地址
port
端口
allowHosts
配置一个白名单列表,只有http请求的host在列表里才正常返回。
disableHostCheck
用于配置是否关闭用于DNS重新绑定的http请求的host检查。默认只接收来自本地的请求,关闭后可以接受来自任意host的请求。
https
默认使用http服务,在某些情况下必须使用https
devServer: {
https: true
}
如果想要配置证书:
devServer: {
key: fs.readFileSync('path/to/server.key'),
cert: fs.readFileSync('path/to/server.crt'),
ca: fs.readFileSync('path/to/ca.pem')
}
clientLogLevel
日至等级
compress
是否启用Gzip压缩,为boolean型,默认为false。
open
是否自动打开浏览器
其他配置项
Target
js应用场景越来越多,从浏览器到node.js,这些运行在不同环境的js代码存在一些差异。target配置项可以让webpack构建出针对不同运行环境的代码。
target值: web, node, async-node, webworker, electron-main, electron-reanderer
Devtool
配置webpack如何生成source map,默认值是false,不生成source map,若想构建出的代码生成source-map:
devtool: 'source-map'
watch和watchOptions
支持文件监听,文件发生变化时重新编译。
watchOptions 配置项更灵活地控制监听模式。
Externals
用来告诉webpack要构建的代码中使用了哪些不用背打包的模块,也就是说这些模板是外部环境提供,webpack在打包时可以忽略它们。
ResolveLoader
告诉webpack如何去寻找loader