一,概述
本文将简单介绍 webpack 的基本用途以及它的四个基本概念 Entry(入口文件),Loader(加载器),Output(输出文件) 和 Plugins(插件).
Webpack
是一个 Javascript 程序的静态资源打包器, 递归地分析文件并建立一个依赖关系图, 然后把所有模块和他们的依赖打包进一个或者多个文件中, 它是高度可配置的, 下面是它的四个核心概念.
Entry(入口文件)
指定了 webpack 该从那个文件开始去分析和建立依赖关系, webpack 可找出文件的直接依赖和间接依赖.每个依赖会被打包进一个成为 bundle 的文件中.我们可以通过设置配置文件中的 entry 属性来指定一个或者多个 Entry(入口文件).
Output(输出文件)
webpack.config.js
module.exports = {
entry: './path/to/my/entry/file.js'
};
output 属性规定了 webpack 该在哪里存放它打包好的 bundle 文件, 以及规定这些文件的的命名.
Loaders(加载器)
webpack.config.js const path = require('path');
module.exports = {
entry: './path/to/my/entry/file.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'my-first-webpack.bundle.js'
}
};
Loaders 使 webpack 能够处理除了 Javascript 之外的文件 (如 CSS), webpack 本身只支持处理 Javascript 文件, loaders 能将特殊的文件转化为 webpack 能够处理的有效的模块 (通过 module 选项).
在 webpack 配置文件中, loaders 主要有两方面的配置:
指定哪些类型的文件应该由对应的 loader 来处理 (通过 test 属性正则匹配文件)
转换这些文件使之能够被添加到依赖图中 (use 属性)
上述配置中使用了包含两个必要子属性 test 和 use 的 rules 属性, 规定了当 webpack 遇到. txt 文件时, 先使用 raw-loader 进行转换, 再打包到 bundle 文件中.注意上述 rules 是在 module 下定义的.
webpack.config.js const path = require('path');
const config = {
entry: './path/to/my/entry/file.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'my-first-webpack.bundle.js'
},
module: {
rules: [{
test: /.txt$/,
use: 'raw-loader'
}]
}
};
module.exports = config;
Plugins(插件)
loaders 用来处理特定的文件, 而 plugins 可以用来执行更广泛,更复杂的任务.plugins 的能力范围从优化,压缩到定义 environment-like 的变量.plugins 接口是非常强大的.
为了使用插件, 必须使用 require() 方法引入它, 并把它加入到 plugins 数组中, 大多数插件可以通过指定选项来进行自定义配置.由于你可以在一个配置文件中多次使用同一类型的插件用作不同的目的, 所以你使用插件之前需要使用 new 操作符创建它的实例对象.
二,Entry Points(入口文件)
webpack.config.js const htmlWebpackPlugin = require('html-webpack-plugin'); //通过npm安装的插件
const webpack = require('webpack'); //访问内置插件
const path = require('path');
const config = {
entry: './path/to/my/entry/file.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'my-first-webpack.bundle.js'
},
module: {
rules: [{
test: /\.txt$/,
use: 'raw-loader'
}]
},
plugins: [new webpack.optimize.UglifyJsPlugin(), new HtmlWebpackPlugin({
template: './src/index.html'
})]
};
module.exports = config;`
有许多方法可以在配置文件中定义 Entry Points
单入口 (简写) 语法
用法:
它是以下配置的简写:
entry: string | Array < string >
webpack.config.js
const config = {
entry: './path/to/my/entry/file.js'
};
module.exports = config;
若使用数组, 那就变成了多入口文件配置.
webpack.config.js
const config = {
entry: {
main: './path/to/my/entry/file.js'
}
};
module.exports = config;
对象语法
用法:
这种方式是最灵活的, 可伸缩的.Scalable webpack configurations / 可伸缩 webpack 配置 指的是可重用的, 并且可以与其他局部配置文件进行合并的配置.这是一个流行的技术用来分离不同的环境或运行时的配置文件, 然后通过 webpack-merge 等工具进行配置的整合.
entry: { [entryChunkName: string] : string | Array < string >
}
webpack.config.js const config = {
entry: {
app: './src/app.js',
vendors: './src/vendors.js'
}
};
应用场景
下面是一些有关 entry 配置的真实用例
1. 分离应用程序 (app) 和第三方库(vendor) 入口
这是什么?
webpack.config.js
const config = {
entry: {
app: './src/app.js',
vendors: './src/vendors.js'
}
};
从表面上看,这告诉我们 webpack 从 app.js 和 vendors.js 开始创建依赖图 (dependency graph).这些依赖图是彼此完全分离,互相独立的(每个 bundle 中都有一个 webpack 引导(bootstrap)).这种方式比较常见于,只有一个入口起点(不包括 vendor) 的单页应用程序 (single page application) 中.
为什么?
此设置允许你使用 CommonsChunkPlugin 从「应用程序 bundle」中提取 vendor 引用 (vendor reference) 到 vendor bundle,并把引用 vendor 的部分替换为 webpack_require() 调用.如果应用程序 bundle 中没有 vendor 代码,那么你可以在 webpack 中实现被称为长效缓存的通用模式.
2. 多页面应用程序
这是什么?
webpack.config.js const config = {
entry: {
pageOne: './src/pageOne/index.js',
pageTwo: './src/pageTwo/index.js',
pageThree: './src/pageThree/index.js'
}
};
告诉 webpack 需要 3 个独立分离的依赖图 (如上面的示例)
为什么?
在多页应用中,每当页面跳转时,服务器将为你获取一个新的 HTML 文档.页面重新加载新文档,并且资源被重新下载.然而,这给了我们特殊的机会去做很多事:
使用 CommonsChunkPlugin 为每个页面间的应用程序共享代码创建 bundle.由于入口起点增多,多页应用能够复用入口起点之间的大量代码 / 模块,从而可以极大地从这些技术中受益
根据经验:每个 HTML 文档应该只使用一个入口文件
三,Loaders(加载器)
Loader 用于对模块的源代码进行转换. loader 可以使你在 import 或 "加载" 模块时预处理文件. 因此,loader 类似于其他构建工具中 "任务 (task)", 并提供了处理前端构建步骤的强大方法. loader 可以将文件从不同的语言(如 TypeScript) 转换为 JavaScript, 或将内联图像转换为 DataURL. loader 甚至允许你直接在 JavaScript 模块中 importCSS 文件
例子
如果要求 webpack 处理 css 和 Typescript 文件, 首先需要从 npm 安装对应的 loader
然后在配置文件中进行设置
npm install --save-dev css-loader
npm install --save-dev ts-loader
loaders 使用方式
webpack.config.js
module.exports = {
module: {
rules: [
{ test: /\.css$/, use: 'css-loader' },
{ test: /\.ts$/, use: 'ts-loader' }
]
}
};
Configuration(推荐): 在配置文件中进行配置
Inline: 在每个 import 语句中额外指明所使用的 loader
CLI: 在 Shell 命令中指定 loader
1. Configuration 方式配置
module.rules 允许你在 webpack 配置中指定多个 loader. 这是展示 loader 的一种简明方式, 并且有助于使代码变得简洁. 同时让你对各个 loader 有个全局概览
2. Inline 方式配置
module: {
rules: [{
test: /\.css$/,
use: [{
loader: ['style-loader'](/loaders/style - loader)
},
{
loader: ['css-loader'](/loaders/css - loader),
options: {
modules: true
}
}]
}]
}
可以在 import 语句或任何等效于 "import" 的方式中指定 loader. 使用! 将资源中的 loader 分开. 分开的每个部分都相对于当前目录解析
import Styles from 'style-loader!css-loader?modules!./styles.css';
这可以覆盖 Configuration 中的 loader 设置, 并且可以? 进行传参参数可以使 JSON 对象
3. CLI 方式配置
命令行示例
webpack--module - bind jade - loader--module - bind 'css=style-loader!css-loader'
上述命令使用对. jade 文件使用 jade-loader, 对 css 文件使用 style-loader 和 css-loader
任何情况下, 都应该尽量使用配置文件的方式来配置 loader
loader 特性
loader 支持链式传递. 能够对资源使用流水线 (pipeline). 一组链式的 loader 将按照先后顺序进行编译. loader 链中的第一个 loader 返回值给下一个 loader. 在最后一个 loader,返回 webpack 所预期的 JavaScript
loader 可以是同步的,也可以是异步的
loader 运行在 Node.js 中,并且能够执行任何可能的操作
loader 接收查询参数. 用于对 loader 传递配置
loader 也能够使用 options 对象进行配置
除了使用 package.json 常见的 main 属性,还可以将普通的 npm 模块导出为 loader,做法是在 package.json 里定义一个 loader 字段
插件 (plugin) 可以为 loader 带来更多特性
loader 能够产生额外的任意文件
loader 通过(loader)预处理函数,为 JavaScript 生态系统提供了更多能力. 用户现在可以更加灵活地引入细粒度逻辑,例如压缩,打包,语言翻译和其他更多.
四,Output(输出文件)
配置 output 选项可以控制 webpack 如何向硬盘写入编译文件.注意, 虽然可以存在多个入口文件, 但只能指定一个输出配置
用法
设置 output 的最低需求是在配置文件的 output 属性值中指定以下两个选项:
filename: 输出文件的文件名
path: 输出文件的绝对路径
该配置会在
webpack.config.js const config = {
output: {
filename: 'bundle.js',
path: '/home/proj/public/assets'
}
};
module.exports = config;
/home/proj / public / assets
中生成 bundle.js 文件
多入口文件配置
如果配置创建了多个单独的 "chunk"(例如,使用多个入口文件或使用像 CommonsChunkPlugin 这样的插件), 则应该使用占位符 (substitutions) 来确保每个文件具有唯一的名称.
高级用法
{
entry: {
app: './src/app.js',
search: './src/search.js'
},
output: {
filename: '[name].js',
path: __dirname + '/dist'
}
}
// 写入磁盘: ./dist/app.js, ./dist/search.js
CDN 上使用资源 Hash
在编译时不知道最终输出文件的 publicPath 的情况下,publicPath 可以留空, 并且在入口起点文件运行时使用
output: {
path: "/home/proj/cdn/assets/[hash]",
publicPath: "http://cdn.example.com/assets/[hash]/"
}
__webpack_public_path__
动态设置
五,Plugins(插件)
__webpack_public_path__ = myRuntimePublicPath
// 剩余的应用程序入口
插件是 webpack 中的支柱功能, webpack 本身也是构建于同一套插件系统之上, 插件是为了解决 loader 无法解决的事情
剖析
webpack 插件是一个具有 apply 方法的 javascript 对象. 这个 apply 被 webpack compiler 调用, 从而使插件获得对 webpack 编译的整个生命周期的访问能力
用法
ConsoleLogOnBuildWebpackPlugin.js
function ConsoleLogOnBuildWebpackPlugin() {};
ConsoleLogOnBuildWebpackPlugin.prototype.apply = function(compiler) {
compiler.plugin('run',
function(compiler, callback) {
console.log("The webpack build process is starting!!!");
callback();
});
};
由于插件可以携带参数 / 选项,你必须在 webpack 配置中, 向 plugins 属性传入 new 实例
根据使用 webpack 的方式, 插件也有多种使用方式
Configuration 方式使用
Node API 方式使用
webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin'); //installed via npm
const webpack = require('webpack'); //to access built-in plugins
const path = require('path');
const config = {
entry: './path/to/my/entry/file.js',
output: {
filename: 'my-first-webpack.bundle.js',
path: path.resolve(__dirname, 'dist')
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
use: 'babel-loader'
}
]
},
plugins: [
new webpack.optimize.UglifyJsPlugin(),
new HtmlWebpackPlugin({template: './src/index.html')
]
};
module.exports = config;
即便使用 Node API,用户也应该在配置文件中配置插件, compiler.apply 并不是推荐的使用方式
some - node - script.js const webpack = require('webpack'); //访问 webpack 运行时(runtime)
const configuration = require('./webpack.config.js');
let compiler = webpack(configuration);
compiler.apply(new webpack.ProgressPlugin());
compiler.run(function(err, stats) {
// ...
});
来源: http://www.jianshu.com/p/299dce603b5a