『构建工具-Webpack』相关内容整理
Webpack是什么?
webpack is a module bundler.
Webpack是一个模块打包器。
webpack 是一个现代 JavaScript 应用程序的*模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph)*,其中包含应用程序需要的每个模块,然后将所有这些模块打包成少量的 bundle - 通常只有一个,由浏览器加载。
Webpack的特点:
- 代码拆分:
Webpack 有两种组织模块依赖的方式,同步和异步。异步依赖作为分割点,形成一个新的块。在优化了依赖树后,每一个异步区块都作为一个文件被打包。
- Loader:
Webpack 本身只能处理原生的 JavaScript 模块,但是 loader 转换器可以将各种类型的资源转换成Javascript 模块。这样,任何资源都可以成为 Webpack 可以处理的模块。
- 智能解析:
Webpack 有一个智能解析器,几乎可以处理任何第三方库,无论它们的模块形式是 CommonJS、 AMD 还是普通的 js 文件。甚至在加载依赖的时候,允许使用动态表达式 require(“./templates/“ + name + “.jade”)。
- 插件系统:
Webpack 还有一个功能丰富的插件系统。大多数内容功能都是基于这个插件系统运行的,还可以开发和使用开源的 Webpack 插件,来满足各式各样的需求。
- 快速运行:
Webpack 使用异步 I/O 和多级缓存提高运行效率,这使得 Webpack 能够以令人难以置信的速度快速增量编译。
Webpack与Gulp的区别?
- gulp:
gulp强调的是前端开发的工作流程,我们可以通过配置一系列的task,定义task处理的事务(例如文件压缩合并、雪碧图、启动server、版本控制等),然后定义执行顺序,来让gulp执行这些task,从而构建项目的整个前端开发流程。
PS:Automate and enhance your workflow
- webpack:
webpack是一个前端模块化方案,更侧重模块打包,我们可以把开发中的所有资源(图片、js文件、css文件等)都看成模块,通过loader(加载器)和plugins(插件)对资源进行处理,打包成符合生产环境部署的前端资源。
PS:webpack is a module bundle
Webpack的核心概念:
Web是高度可配置的,在开始前需要先理解四个核心概念:入口(entry)、输出(output)、loader、插件(plugins)。
entry: 在 webpack 中,我们使用 webpack 配置对象(webpack configuration object)中的
entry
属性来定义入口。看一个最简单的例子:module.exports = { entry: './path/to/my/entry/file.js' };
Output:将所有的资源(assets)归拢在一起后,还需要告诉 webpack 在哪里打包应用程序。webpack 的
output
属性描述了如何处理归拢在一起的代码(bundled code)。例子: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' } };
Loader: webpack loader 在文件被添加到依赖图中时,其转换为模块。例子:
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:想要使用一个插件,你只需要
require()
它,然后把它添加到plugins
数组中。多数插件可以通过选项(option)自定义。你也可以在一个配置文件中因为不同目的而多次使用同一个插件,这时需要通过使用new
来创建它的一个实例。例子: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: { 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;
参考资料:核心概念简介
Webpack的安装配置:
前提条件:
请安装和使用 Node.js 最新的长期支持版本(LTS - Long Term Support),使用旧版本,你可能遇到各种问题,因为它们可能缺少 webpack 功能以及/或者缺少相关 package 包。
本地安装:
最新版本的webpack是: Github-Webpack-Releases
npm install -g webpack --save-dev
安装完成之后,会在package.json
中会添加如下信息:
"devDependencies": {
"webpack": "^3.4.1"
}
对于大多数项目,建议本地安装。这可以使我们在引入破坏式变更(breaking change)的依赖时,更容易分别升级项目。一般不推荐全局安装 webpack。这会将您项目中的 webpack 锁定到指定版本,并且在使用不同的 webpack 版本的项目中,可能会导致构建失败。
Webpack的简单使用:
构建项目:
新建一个index.js
文件,在跟该文件中编写一个函数:
// index.js 文件
function func(str) {
alert(str);
}
编写完成之后可以使用webpack
命令了来打包index.js
文件,如下所示:
语法: webpack [待打包文件] [打包完成文件名]
例子: webpack index.js index.bundle.js
➜ js webpack index.js index.bundle.js
Hash: 72aeecc257bb3571dac7
Version: webpack 3.4.1
Time: 61ms
Asset Size Chunks Chunk Names
index.bundle.js 2.51 kB 0 [emitted] main
[0] ./index.js 37 bytes {0} [built]
打包输出信息说明:
Name | Description |
---|---|
Hash | 文件的HASH值 |
Version | webpack的版本 |
Time | 打包所花费的时间 |
Asset | 打包生成的文件 |
Size | 生成文件的大小 |
Chunks | 打包的分块 |
Chunk Names | 打包的块名称 |
这样就完成了一次简单的打包操作,打包完成之后可以打开index.bundle.js
查看一下,Webpack会自动给该文件中添加一些注释还会给一些模块进行编号。
参考资料:Webpack官网简单Demo
Webpack的基本配置:
按照如下目录结构进行构建一个项目:
➜ ~ tree Webpack
Webpack
├── dist
│ ├── css
│ └── js
├── node_modules
├── package-lock.json
├── package.json
├── src
│ ├── css
│ │ └── style.css
│ ├── index.html
│ └── js
│ └── index.js
└── webpack.config.js
7 directories, 6 files
webpack.config.js
编写webpack.config.js
文件:
const webpack = require('webpack');
module.exports = {
entry:'./src/js/index.js',
output:{
path:'/Users/Yang/Documents/Webstorm-Work/Webpack/dist/js', // 设置输出目录
filename:'[name].bundle.js' // 输出文件名
},module:{
loaders:[
test:/\.css$/,//支持正则
loader:'style-loader!css-loader'
]
},resolve:{
//添加在此的后缀所对应的文件可以省略后缀
extensions: ['', '.js', '.json', '.css', '.scss']
},plugins:[
new webpack.BannerPlugin('This file is created by ly'); // 插件设置
]
}
Webpack的Loader使用:
loader 用于对模块的源代码进行转换。loader 可以使你在 import
或”加载”模块时预处理文件。因此,loader 类似于其他构建工具中“任务(task)”,并提供了处理前端构建步骤的强大方法。loader 可以将文件从不同的语言(如 TypeScript)转换为 JavaScript,或将内联图像转换为 data URL。loader 甚至允许你直接在 JavaScript 模块中 import
CSS文件!
简单示例:
可以使用 loader 告诉 webpack 加载 CSS 文件,或者将 TypeScript 转为 JavaScript。为此,首先安装相对应的 loader:
npm install --save-dev css-loader # CSS loader
npm install --save-dev ts-loader # TypeScript loader
然后指示 webpack 对每个 .css
使用 css-loader
,以及对所有 .ts
文件使用 ts-loader
:
webpack.config.js
module.exports = {
module: {
rules: [
{ test: /\.css$/, use: 'css-loader' },
{ test: /\.ts$/, use: 'ts-loader' }
]
}
};
使用 Loader:
在应用程序中,有三种使用 loader 的方式:
- 配置(推荐):在 webpack.config.js 文件中指定 loader。
- 内联:在每个
import
语句中显式指定 loader。 - CLI:在 shell 命令中指定它们。
配置[Configuration]:
module.rules
允许你在 webpack 配置中指定多个 loader。 这是展示 loader 的一种简明方式,并且有助于使代码变得简洁。同时让你对各个 loader 有个全局概览:
module: {
rules: [
{
test: /\.css$/,
use: [
{ loader: 'style-loader' },
{
loader: 'css-loader',
options: {
modules: true
}
}
]
}
]
}
内联:
可以在 import
语句或任何等效于 “import” 的方式中指定 loader。使用 !
将资源中的 loader 分开。分开的每个部分都相对于当前目录解析。
import Styles from 'style-loader!css-loader?modules!./styles.css';
通过前置所有规则及使用 !
,可以对应覆盖到配置中的任意 loader。
选项可以传递查询参数,例如 ?key=value&foo=bar
,或者一个 JSON 对象,例如 ?{"key":"value","foo":"bar"}
。
尽可能使用
module.rules
,因为这样可以减少源码中的代码量,并且可以在出错时,更快地调试和定位 loader 中的问题。
CLI:
你也可以通过 CLI 使用 loader:
webpack --module-bind jade-loader --module-bind 'css=style-loader!css-loader'
这会对 .jade
文件使用 jade-loader
,对 .css
文件使用 style-loader
和 css-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 生态系统提供了更多能力。用户现在可以更加灵活地引入细粒度逻辑,例如压缩、打包、语言翻译和其他更多。
解析 Loader:
loader 遵循标准的模块解析。多数情况下,loader 将从模块路径(通常将模块路径认为是 npm install
, node_modules
)解析。
loader 模块需要导出为一个函数,并且使用 Node.js 兼容的 JavaScript 编写。通常使用 npm 进行管理,但是也可以将自定义 loader 作为应用程序中的文件。按照约定,loader 通常被命名为 xxx-loader
(例如 json-loader
)。有关详细信息,请查看如何编写 loader?。
参考资料:Webpack-Loader详解
Webpack的CLI使用:
Output:
通过以下这些配置,你可以调整构建流程的某些输出参数。
常用参数说明:
参数 | 说明 | 输入类型 | 默认值 |
---|---|---|---|
–output-chunk-filename | 输出的附带 chunk 的文件名 | string | 含有[id] 的文件名,而不是 [name] 或者 [id] 作为前缀 |
–output-filename | 打包文件的文件名 | string | [name].js |
–output-jsonp-function | 加载 Chunk 时使用的 JSONP 函数名 | string | webpackJsonp |
–output-library | 以库的形式导出入口文件 | string | |
–output-library-target | 以库的形式导出入口文件时,输出的类型 | string | var |
–output-path | 输出的路径(在公共路径的基础上) | string | 当前目录 |
–output-pathinfo | 加入一些依赖信息的注解 | boolean | false |
–output-public-path | 输出文件时使用的公共路径 | string | / |
–output-source-map-filename | 生成的 SourceMap 的文件名 | string | [name].map or [outputFilename].map |
Debug:
以下这些配置可以帮助你在 Webpack 编译过程中更好地 debug。
常用参数说明:
参数 | 说明 | 输入类型 | 默认值 |
---|---|---|---|
–debug | 把 loader 设置为 debug 模式 | boolean | false |
–devtool | 为打包好的资源定义source map 的类 | string | - |
–progress | 打印出编译进度的百分比值 | boolean | false |
Model:
这些配置可以用于绑定 Webpack 允许的模块。
常用参数说明:
参数 | 说明 | 使用方法 |
---|---|---|
–module-bind | 为 loader 绑定一个扩展 | –module-bind js=babel-loader |
–module-bind-post | 为 post loader 绑定一个扩展 | |
–module-bind-pre | 为 pre loader 绑定一个扩展 |
Watch:
这些配置可以用于观察依赖文件的变化,一旦有变化,则可以重新执行构建流程。
常用参数说明:
参数 | 说明 |
---|---|
–watch, -w | 观察文件系统的变化 |
–save, -s | 在保存的时候重新编译,无论文件是否变化 |
–watch-aggregate-timeout | 指定一个毫秒数,在这个时间内,文件若发送了多次变化,会被合并 |
–watch-poll | 轮询观察文件变化的时间间隔(同时会打开轮询机制 |
–watch-stdin, –stdin | 当 stdin 关闭时,退出进程 |
Optimize:
在生产环境的构建时,这些配置可以用于调整的一些性能相关的配置。
常用参数说明:
参数 | 解释说明 | 使用的插件 |
---|---|---|
–optimize-max-chunks | 限制 chunk 的数量 | LimitChunkCountPlugin |
–optimize-min-chunk-size | 限制 chunk 的最小体积 | MinChunkSizePlugin |
–optimize-minimize | 压缩混淆 javascript,并且把 loader 设置为 minimizing | UglifyJsPlugin & LoaderOptionsPlugin |
Resolve:
这些配置可以用于设置 webpack resolver 时使用的别名(alias)和扩展名(extension)。
常用参数说明:
参数 | 说明 | 示例 |
---|---|---|
–resolve-alias | 指定模块的别名 | –resolve-alias jquery-plugin=jquery.plugin |
–resolve-extensions | 指定需要被处理的文件的扩展名 | –resolve-extensions .es6 .js .ts |
–resolve-loader-alias | Minimize javascript and switches loaders to minimizing |
Display:
以下选项用于配置 Webpack 在控制台输出的统计数据,以及这些数据的样式。
常用参数说明:
参数 | 说明 | 类型 |
---|---|---|
–color, –colors | 开启/关闭控制台的颜色 [默认值: (supports-color)] | boolean |
–display-cached | 在输出中显示缓存的模块 | boolean |
–display-cached-assets | 在输出中显示缓存的 assets | boolean |
–display-chunks | 在输出中显示 chunks | boolean |
–display-depth | 显示从入口起点到每个模块的距离 | boolean |
–display-entrypoints | 在输出中显示入口文件 | boolean |
–display-error-details | 显示详细的错误信息 | boolean |
–display-exclude | 在输出中显示被排除的文件 | boolean |
–display-max-modules | 设置输出中可见模块的最大数量 | number |
–display-modules | 在输出中显示所有模块,包括被排除的模块 | boolean |
–display-optimization-bailout | 作用域提升回退触发器(Scope hoisting fallback trigger)(从 webpack 3.0.0 开始) | boolean |
–display-origins | 在输出中显示最初的 chunk | boolean |
–display-provided-exports | 显示有关从模块导出的信息 | boolean |
–display-reasons | 显示模块包含在输出中的原因 | boolean |
–display-used-exports | 显示模块中被使用的接口(Tree Shaking) | boolean |
–hide-modules | 隐藏关于模块的信息 | boolean |
–sort-assets-by | 对 assets 列表以某种属性排序 | string |
–sort-chunks-by | 对 chunks 列表以某种属性排序 | string |
–sort-modules-by | 对模块列表以某种属性排序 | string |
–verbose | 显示更多信息 | boolean |
–display | 选择显示预设(verbose - 繁琐, detailed - 细节, normal - 正常, minimal - 最小, errors-only - 仅错误, none - 无; 从 webpack 3.0.0 开始) | string |
Other:
参数 | 说明 | 用法 | |
---|---|---|---|
–bail | 一旦发生错误,立即终止 | ||
–cache | 开启缓存 [watch 时会默认打开] | –cache=false | |
–define | 定义 bundle 中的任意自由变量,查看 shimming | –define process.env.NODE_ENV=’development’ | |
–hot | 开启模块热替换 [使用 HotModuleReplacementPlugin] | -hot=true | |
–labeled-modules | Enables 开启模块标签 [使用 LabeledModulesPlugin] | ||
-plugin | 加载某个插件 | ||
–prefetch | 预加载某个文件 | –prefetch=./files.js | |
–provide | 在所有模块中将这些模块提供为自由变量,查看 shimming | –provide jQuery=jquery | |
–records-input-path | 记录文件的路径(读取) | ||
–records-output-path | 记录文件的路径(写入) | ||
–records-path | 记录文件的路径 | ||
–target | 目标的执行环境 | –target=’node’ |
参考资料:Webpack-CLI使用