webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。
当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),
其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle;
Webpack 是一个前端资源加载/打包工具。
它将根据模块的依赖关系进行静态分析,然后将这些模块按照指定的规则生成对应的静态资源。
(1)指示 webpack 应该使用哪个模块,来作为构建其内部依赖图的开始。进入入口起点后,webpack 会找出有哪些模块和库是入口起点(直接和间接)依赖的
每个依赖项随即被处理,最后输出到称之为 bundles 的文件中;
可以通过在 webpack 配置中配置 entry 属性,来指定一个入口起点(或多个入口起点)。默认值为 ./src
(2)webpack配置中定义entry属性的多种方式:
1.1 单个入口简写语法: entry: string|Array
const config = {
entry: './path/to/my/entry/file.js'
};
module.exports = config;
entry 属性的单个入口语法,是下面的简写:
const config = {
entry: {
main: './path/to/my/entry/file.js'
}
};
总结:当在寻找为只有一个入口起点的应用程序或工具(即 library)快速设置 webpack 配置的时候,这很不错。然而,使用此语法在扩展配置时有失灵活性
1.2 对象语法: entry: {[entryChunkName: string]: string|Array}
const config = {
entry: {
app: './src/app.js',
vendors: './src/vendors.js'
}
};
总结:对象语法会比较繁琐。然而,这是应用程序中定义入口的最可扩展的方式
1.3 分离 应用程序(app) 和 第三方库(vendor) 入口示例:
const config = {
entry: {
app: './src/app.js',
vendors: './src/vendors.js'
}
};
这种方式比较常见于,只有一个入口起点(不包括 vendor)的单页应用程序(single page application)中;
1.4 多页面应用程序:
const config = {
entry: {
pageOne: './src/pageOne/index.js',
pageTwo: './src/pageTwo/index.js',
pageThree: './src/pageThree/index.js'
}
};
Webpack 需要 3 个独立分离的依赖图;每个 HTML 文档只使用一个入口起点
output 属性告诉 webpack 在哪里输出它所创建的 bundles,以及如何命名这些文件,默认值为 ./dist。
基本上,整个应用程序结构,都会被编译到你指定的输出路径的文件夹中。
你可以通过在配置中指定一个 output 字段,来配置这些处理过程:
注意:即使可以存在多个入口起点,但只指定一个输出配置
在 webpack 中配置 output 属性的最低要求是,将它的值设置为一个对象,包括以下两点:filename 用于输出文件的文件名 和 目标输出目录 path 的绝对路径:
const config = {
output: {
filename: 'bundle.js',
path: '/home/proj/public/assets'
}
};
module.exports = config;
此配置将一个单独的 bundle.js 文件输出到 /home/proj/public/assets 目录中
如果配置创建了多个单独的 “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
loader 让 webpack 能够去处理那些非 JavaScript 文件(如 TypeScript);
loader 可以将所有类型的文件转换为 webpack 能够处理的有效模块,然后你就可以利用 webpack 的打包能力,对它们进行处理
本质上,webpack loader 将所有类型的文件,转换为应用程序的依赖图(和最终的 bundle)可以直接引用的模块
在更高层面,在 webpack 的配置中 loader 有两个目标:
test 属性,用于标识出应该被对应的 loader 进行转换的某个或某些文件。
use 属性,表示进行转换时,应该使用哪个 loader。
注意:在 webpack 配置中定义 loader 时,要定义在 module.rules 中,而不是 rules
安装相对应的 loader:
npm install --save-dev css-loader
npm install --save-dev ts-loader
在你的应用程序中,有三种使用 loader 的方式:
(1)配置(推荐):在 webpack.config.js 文件中指定 loader。
在配置中使用loader方式示例:
module.exports = {
module: {
rules: [
{ test: /\.css$/, use: 'css-loader' },
{ test: /\.ts$/, use: 'ts-loader' }
]
}
};
(2)内联:在每个 import 语句中显式指定 loader。
可以在 import 语句或任何等效于 “import” 的方式中指定 loader。使用 ! 将资源中的 loader 分开。分开的每个部分都相对于当前目录解析。
import Styles from 'style-loader!css-loader?modules!./styles.css';
(3)CLI:在 shell 命令中指定它们
通过 CLI 使用 loader:
webpack --module-bind jade-loader --module-bind 'css=style-loader!css-loader'
常用Loader:
(1)编译相关: babel-loader、ts-loader
(2)样式相关:style-loader、css-loader、less-loader、postcss-loader
(3)文件相关:file-loader、url-loader
loader特性:
(1)loader 支持链式传递。能够对资源使用流水线(pipeline)。一组链式的 loader 将按照相反的顺序执行。loader 链中的第一个 loader 返回值给下一个 loader。在最后一个 loader,返回 webpack 所预期的 JavaScript。
(2)loader 可以是同步的,也可以是异步的。
(3)loader 运行在 Node.js 中,并且能够执行任何可能的操作。
(4)loader 接收查询参数。用于对 loader 传递配置。
(5)loader 也能够使用 options 对象进行配置。
(6)除了使用 package.json 常见的 main 属性,还可以将普通的 npm 模块导出为 loader,做法是在 package.json 里定义一个 loader 字段。
(7)插件(plugin)可以为 loader 带来更多特性。
(8)loader 能够产生额外的任意文件。
loader 被用于转换某些类型的模块,而插件则可以用于执行范围更广的任务。
插件的范围包括,从打包优化和压缩,一直到重新定义环境中的变量。插件接口功能极其强大,可以用来处理各种各样的任务
想要使用一个插件,你只需要 require() 它,然后把它添加到 plugins 数组中。
多数插件可以通过选项(option)自定义。你也可以在一个配置文件中因为不同目的而多次使用同一个插件,这时需要通过使用 new 操作符来创建它的一个实例
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: {
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;
常用Plugins:
(1)优化相关: CommonsChunkPlugin、UglifyjsWebpackPlugin
(2)功能相关:ExtractTextWebpackPlugin、HtmlWebpackPlugin、HotModuleReplacementWebpackPlugin、CopyWebpackPlugin
通过选择 development 或 production 之中的一个,来设置 mode 参数,你可以启用相应模式下的 webpack 内置的优化
在配置中提供 mode 选项:
module.exports = {
mode: 'production'
};
development:会将 process.env.NODE_ENV 的值设为 development。启用 NamedChunksPlugin 和 NamedModulesPlugin
production:会将 process.env.NODE_ENV 的值设为 production。启用 FlagDependencyUsagePlugin, FlagIncludedChunksPlugin, ModuleConcatenationPlugin, NoEmitOnErrorsPlugin, OccurrenceOrderPlugin, SideEffectsFlagPlugin 和 UglifyJsPlugin.
Chunk:代码块
Bundle:一捆
Module:模块