webpack 是什么, 它自称 MODULE BUNDLER,也就是模块打包器。对于 webpack 来说,所有的文件都可以是模块,都是可以管理、打包处理的。
安装 webpack
和普通的 nodejs 模块一样,我们可以全局安装使其变成全局变量,也可以只在项目中安装。
npm install webpack -g
npm install webpack --save-dev
webpack 配置
webpack 的运行是需要一个配置文件,默认为 webpack.config.js,在项目根目录下。其主要内容为:
var path = require('path');
var webpack = require('webpack');
var ExtractTextPlugin = require("extract-text-webpack-plugin");
module.exports = {
//插件项
plugins: [new ExtractTextPlugin("[name].css")],
//页面入口文件配置
entry: {
index: './src/js/index.js'
},
//入口文件输出配置
output: {
path: path.join(__dirname, 'dist'),
filename: '[name].js'
},
module: {
//加载器配置
loaders: [
{
test: /\.css$/,
loader: ExtractTextPlugin.extract("style-loader", "css-loader")
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: {
// presets: ['es2015','stage-0']
}
},
{
test: /\.(png|jpg)$/,
loader: 'url-loader',
query: {
limit: 8192
}
}
]
},
devServer: {
// historyApiFallback: true,
// hot: true,
inline: true
},
//其它解决方案配置
resolve: {
// module 查找路径
// root: 'E:/github/flux-example/src', //绝对路径
// 可以作为module的文件后缀
extensions: ['', '.js'],
// 模块变量别名
alias: {
// AppStore : 'js/stores/AppStores.js',
// ActionType : 'js/actions/ActionType.js',
// AppAction : 'js/actions/AppAction.js'
}
}
};
基本上都有注释,但是有几个重要的配置项需要单独拿出来说明一下。
entry:
这是配置 webpack 的入口文件。简单的说就是,webpack 打包的时候,会从这里定义的文件开始解决依赖,完成打包。入口文件可以是多个文件,entry 的值可以是一个字符串路径,也可以是一个字符串列表,也可以是一个对象。我这里建议大家用对象配置,因为对象的 key 值会作为名称传入 output 中。
output:
这里配置的是 webpack 打包完成的文件输出。path 定义输出路径,fileName 定义 输出文件名。
这里要着重说明一下,fileName 的值虽然是字符串,但是其中可以有变量存在,比如
fileName: '[name].js'
其中的 [name] 就是 entry 中对象的 key 值!如果你没有把 entry 设置成 对象,那么这里的 [name] 值就是main。当然除了 [name] 变量,还有 [id] 和 [contenthash] 这两个变量可以用。
module
这里就是 webpack 的重头戏。在这里我们可以配置对不同文件应用不同的处理方式。
module: {
//加载器配置
loaders: [
{
test: /\.css$/,
loader: ExtractTextPlugin.extract("style-loader", "css-loader")
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: {
// presets: ['es2015','stage-0']
}
},
{
test: /\.(png|jpg)$/,
loader: 'url-loader',
query: {
limit: 8192
}
}
]
},
test 是用来匹配文件,值为正则表达式;loader 是对匹配的文件应用的处理器,比如对 css 文件应用 css-loader 和 style-loader 处理器;query 是用来传递参数到处理器,也可以直接加载 loader 后面,类似 url 传参;exclude 为排除选项,值也是正则表达式,用来排除不需要处理的文件。
devServer
这里主要是配置和 webpack-dev-server 相关的参数,webpack 也提供一个简易的本地服务器,可以通过链接直接访问 index.html 文件。
同时,webpack 还支持自动刷新,有两种模式 iframe 和 inline,两者的区别在于:
- iframe 模式:我们不访问
http://localhost:8080
,而是访问http://localhost:8080/webpack-dev-server/index.html
- inline 模式:在命令行中指定该模式,
webpack-dev-server --inline
。这样http://localhost:8080/index.html
页面就会在 js 文件变化后自动刷新了。
运行 webpack
webpack 在运行时可以添加参数,其中有一下几个参数是我们用到的最多的。
$ webpack --config XXX.js //使用另一份配置文件(比如webpack.config2.js)来打包
$ webpack --watch //监听变动并自动打包
$ webpack -p //压缩混淆脚本,这个非常非常重要!
$ webpack -d //生成map映射文件,告知哪些模块被最终打包到哪里了
模块引入
1、html 部分
在 html 中引用相应的资源的方式有两种,一种直接引用打包完成后的资源,但缺点是不能自动刷新了;另外一种就是只引用 output 资源名称,然后运行 webpack-dev-server 自动刷新,它会自动替换资源,其中 css 文件也不会要引入,webpack会自动添加到 head 中。
2、JS 部分
在 js 中引用别的资源的方式为 require,其中不论类型,css、image 都可以当成模块引入。
其他
一、shimming
在 AMD/CMD 中,我们需要对不符合规范的模块(比如一些直接返回全局变量的插件)进行 shim 处理,这时候我们需要使用 exports-loader 来帮忙:
{
test: require.resolve("./src/js/tool/swipe.js"),
loader: "exports?swipe"
}
之后在脚本中需要引用该模块的时候,这么简单地来使用就可以了:
require('./tool/swipe.js');
swipe();
二、自定义公共模块提取
在文章开始我们使用了 CommonsChunkPlugin 插件来提取多个页面之间的公共模块,并将该模块打包为 common.js 。
但有时候我们希望能更加个性化一些,我们可以这样配置:
var CommonsChunkPlugin = require("webpack/lib/optimize/CommonsChunkPlugin");
module.exports = {
entry: {
p1: "./page1",
p2: "./page2",
p3: "./page3",
ap1: "./admin/page1",
ap2: "./admin/page2"
},
output: {
filename: "[name].js"
},
plugins: [
new CommonsChunkPlugin("admin-commons.js", ["ap1", "ap2"]),
new CommonsChunkPlugin("commons.js", ["p1", "p2", "admin-commons.js"])
]
};
// <script>s required:
// page1.html: commons.js, p1.js
// page2.html: commons.js, p2.js
// page3.html: p3.js
// admin-page1.html: commons.js, admin-commons.js, ap1.js
// admin-page2.html: commons.js, admin-commons.js, ap2.js
三、独立打包样式文件
有时候可能希望项目的样式能不要被打包到脚本中,而是独立出来作为 css,然后在页面中以 <link> 标签引入。这时候我们需要 extract-text-webpack-plugin 来帮忙:
var ExtractTextPlugin = require("extract-text-webpack-plugin");
module.exports = {
module: {
loaders: [
{ test: /\.css$/, loader: ExtractTextPlugin.extract("style-loader", "css-loader") }
]
},
plugins: [
new ExtractTextPlugin("styles.css")
]
}
四、使用CDN/远程文件
有时候我们希望某些模块走CDN并以<script>的形式挂载到页面上来加载,但又希望能在 webpack 的模块中使用上。
这时候我们可以在配置文件里使用 externals 属性来帮忙:
{
externals: {
// require("jquery") 是引用自外部模块的
// 对应全局变量 jQuery
"jquery": "jQuery"
}
}
需要留意的是,得确保 CDN 文件必须在 webpack 打包文件引入之前先引入。
我们倒也可以使用 script.js 在脚本中来加载我们的模块:
var $script = require("scriptjs");
$script("//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js", function() {
$('body').html('It works!')
});