前言
webpack第二篇, webpack的四个核心概念;
相关链接: webapck
-
入口(Entry):指示 webpack 应该使用哪个模块,来作为构建其内部依赖图的开始
-
输出(Output):在哪里输出它所创建的 bundles
-
模块(Module):在 Webpack 里一切皆模块,一个模块对应着一个文件。Webpack 会从配置的 Entry 开始递归找出所有依赖的模块。
-
代码块(Chunk):,一个 Chunk 由多个模块组合而成,用于代码合并与分割
-
模块转换器(Loader):让 webpack 能够去处理那些非 JavaScript 文件
-
插件(Plugins):用于执行范围更广的任务
Entry
可以通过在 webpack 配置中配置 Entry 属性,来指定一个入口起点(或多个入口起点)。默认值为 ./src。
配置 Entry 属性
单个入口(简写)语法 (用法:entry: string|Array)
webpack.config.js
- Entry 属性的单入口语法:
module.exports = {
entry: {
main: './src/index.js'
}
};
- 以下是单入口文件简写:
module.exports = {
entry: {
main: './src/index.js'
}
};
- 如果想将多个相关的文件配置在一起, 那还可以将文件路径按照数组配置,它会将它们的依赖关系绘制到一个块里(这里解释我是按照官方文档来写的,这里也只是简单的做了配置,没有深入研究,也就按照官方来吧!)
module.exports = {
entry: [
'./src/index.js',
'./src/index_1.js'
],
output: {
filename: 'bundle.js'
}
};
*如果是想用webpack快速配置时, 单入口文件是最好的选择;
对象语法 ( 用法:Entry: {[entryChunkName: string]: string|Array} )
- 对象语法是定义入口的可扩展的方法,可复用,也能与其他部分组合配置组合使用,是目前比较的流行的用法,可按照不同环境,构建的目标和运行时进行分离,然后使用webpack-merge类工具将其合并;
以下是对象语法配置及其实际用例:
webpack.config.js
module.exports = {
entry: {
main: './src/index.js',
main_1: './src/index_1.js'
}
};
Output
在 webpack配置 Output 属性是一个对象,包括以下两点:
-
filename 用于输出文件的文件名。
-
目标输出目录 path 的绝对路径。
-
Entry 属性的单入口 Output 配置如下: webpack.config.js
module.exports = {
output: {
filename: 'bundle.js',
}
};
- Entry 属性的多入口 Output 配置如下: webpack.config.js
module.exports = {
entry: {
main: './src/index.js',
app: './src/index.js'
},
output: {
filename: '[name].js', // 使用占位符
path: __dirname + '/dist'
}
};
- 打包html的js引用带上 cdn域名, 配置如下:
webpack.config.js
module.exports = {
//...
output: {
publicPath: 'https://cdn.com.cn', // 使用publicPath 这个配置项
filename: '[name].js', // 使用占位符
path: __dirname + '/dist'
}
};
在编译时不知道 publicPath 情况下,publicPath 是可以置空;并在运行时通过入口点文件中的__webpack_public_path__变量进行动态设置
Loader
什么是Loader
webpack仅能理解JavaScript和JSON文件, 那这里 webpack 就需要用到 Loader 来预处理文件。使我们能打包除 JavaScript 之外的任何静态资源,Loader 对模块的源代码进行转换,可以使你在 import 或"加载"模块时预处理文件,具体的相关文档 loader
简单来说 Loader 是一个转换器,用于对源代码进行转换,输出新的结果;
以图片文件为例: 如果我想要加载图片 .jepg 的文件, 或者将 TypeScript 转为 JavaScript。为此,首先安装相对应的 loader:
安装 loader工具;
npm install -D file-loader
npm install --save-dev ts-loader
然后在 webpack 对每个 .jepg 使用 file-loader,对所有 .ts 文件使用 ts-loader:
module: {
rules: [
{
test: /\.jpeg$/,
use: {
loader: 'file-loader'
}
},
{
test: /\ts/,
use: 'ts-loader'
}
]
}
运行
npm run build
图片打包配置完成之后在dist目录下可以看的有一个图片文件;
使用 Loader
应用程序中有三种使用 Loader 方法:
- 配置(推荐):在 webpack.config.js 文件中指定 Loader。
- 内联:在每个 import 语句中显式指定 loader。
- CLI:在 shell 命令中指定它们。
配置[Configuration]
module.rules 允许在 webpack 配置中指定多个 Loader。 这是展示 Loader 的一种简明方式,并且有助于使代码变得简洁。同时让你对各个 Loader 有个全局概览:
module: {
rules: [
{
test: /\.jpeg$/,
use: {
loader: 'file-loader'
}
},
{
test: /\ts/,
use: 'ts-loader'
}
]
}
内联
可以在 import 语句或任何等效于 "import" 的方式中指定 Loader。使用 ! 将资源中的 Loader 分开。分开的每个部分都相对于当前目录解析。
通过前置所有规则及使用 !,可以对应覆盖到配置中的任意 Loader。
选项可以传递查询参数,例如 ?key=value&foo=bar,或者一个 JSON 对象,例如 ?{"key":"value","foo":"bar"}。
尽可能使用 module.rules,因为这样可以减少源码中的代码量,
这样在出错时更快地调试和定位 loader 中的问题。
CLI
通过 CLI 使用 Loader:
这样会对 .ts 文件使用 ts-loader,对 .css 文件使用 style-loader 和 css-loader。
- 不同的 Loader 可以打包不同的静态资源
- 以下是整理的一些我配置webpack 经常会使用到的loader
| 类型 | Loader | 作用 |
|---|---|---|
| 文件 | url-loader | 像 file loader 一样工作,但如果文件小于限制,可以返回 data URL |
| 文件 | file-loader | 将文件发送到输出文件夹,并返回(相对)URL |
| 转换编译(Transpiling) | babel-loader | 使用Babel加载ES2015 +代码并转换为ES5 |
| 转换编译(Transpiling) | ts-loader | 像JavaScript一样加载TypeScript 2.0+ |
| 模板(Templating) | html-loader | 导出 HTML 为字符串,需要引用静态资源 |
| 样式 | style-loader | 将模块的导出作为样式添加到 DOM 中 |
| 样式 | css-loader | 解析 CSS 文件后,使用 import 加载,并且返回 CSS 代码 |
| 样式 | less-loader | 加载和转译 LESS 文件中 |
| 样式 | sass-loader | 加载和转译 SASS/SCSS 文件 |
| 样式 | postcss-loader | 使用 PostCSS 加载和转译 CSS/SSS 文件 |
| 样式 | eslint-loader | 使用ESLint整理代码的PreLoader |
| 框架(Frameworks) | vue-loader | 加载 Vue 组件 |
| 框架(Frameworks) | eslint-loader | 使用ESLint整理代码的PreLoader |
Loader 打包静态资源(图片)
- 设置图片文件名
module: {
rules: [
{
test: /\.jpeg$/,
use: {
loader: 'file-loader',
options: {
// placeholder 占位符
name: '[name].[ext]' // 打包源文件的名称和后缀
// name: '[name]_[hash].[ext]' // 打包加上 hash 值的文件名称
}
}
}
]
},
Plugins
我们看一下官网的定义,webpack 插件由以下部分组成:
-
webpack 插件是一个具有 apply 属性的 JavaScript 对象。
-
apply 属性会被 webpack compiler 调用,并且 compiler 对象可在整个编译生命周期访问。
-
插件目的在于解决 loader 无法实现的其他事
ConsoleLogOnBuildWebpackPlugin.js
const pluginName = 'ConsoleLogOnBuildWebpackPlugin';
class ConsoleLogOnBuildWebpackPlugin {
apply(compiler) {
compiler.hooks.run.tap(pluginName, compilation => {
console.log("webpack 构建过程开始!");
});
}
}
compiler hook 的 tap 方法的第一个参数,应该是驼峰式命名的插件名称。建议为此使用一个常量,以便它可以在所有 hook 中复用。 具体参考官方文档;
配置
由于插件可以携带参数/选项,你必须在 webpack 配置中,向 plugins 属性传入 new 实例。 根据你的 webpack 用法,这里有多种方式使用插件
安装 Plugins 插件;
npm install --save-dev html-webpack-plugin
npm install --save-dev uglifyjs-webpack-plugin
webpack.config.js
const path = require('path')
const uglifyJsPlugin = require('uglifyjs-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
mode: 'none',
entry: './index.js',
module: {
rules: [
{
test: /\.(jpeg|png|svg|gif|jpg)$/,
use: {
loader: 'url-loader',
options: {
limit: 20480
}
}
},
{
test: /\.(eot|woff|ttf)$/,
use: {
loader: 'file-loader'
}
},
{
test: /\.(scss)$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2
}
},
'sass-loader',
'postcss-loader'
],
}
]
},
plugins: [
new uglifyJsPlugin(), //压缩js文件
new HtmlWebpackPlugin({
minify: { // 是对html文件进行压缩,removeAttrubuteQuotes 是却掉属性的双引号。
removeAttributeQuotes: true
},
hash: true, // 为了开发中js有缓存效果,所以加入hash,这样可以有效避免缓存JS。
template: path.resolve(__dirname, './index.html'), //是要打包的html模版路径和文件名称。
filename: 'index.html'
}),
],
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
}
}
执行命令后 在 dist 目录下有一个 index.html 和 bundle.js;同时 index.html 已经自动引入了 bundle.js, 查看 bundle.js 文件看到代码也是压缩的 js 文件
参考资料
后语
前路漫漫 ~~