这是我参与11月更文挑战的第10天,活动详情查看:2021最后一次更文挑战
在第一篇之后我们对webpack有了基础的了解,webpack最开始是用来打包JavaScript的,如今越来越多的文件类型,webpack本身是不支持打包的,怎么办了?就引入了我们今天主要讨论的loader呢,用来扩展webpack对多种类型的文件进行打包输出。
loader篇
loader 用于对模块的源代码进行转换。loader 可以使你在 import 或 "load(加载)" 模块时预处理文件。可以将文件从不同的语言(如 TypeScript)转换为 JavaScript 或将内联图像转换为 data URL。loader 甚至允许你直接在 JavaScript 模块中 import CSS 文件。
CSS篇
在开发过程中我们不可避免的会写css文件,甚至less、scss文件等,这里以css文件举例。先将代码改成以下内容。添加一个css文件,在index.js中引入该文件,如下所示
// /src/index.css
.hello {
color: red;
}
import _ from 'lodash';
import './index.css'
function component() {
const element = document.createElement('div');
// lodash(目前通过一个 script 引入)对于执行这一行是必需的
element.innerHTML = _.join(['Hello', 'webpack'], ' ');
element.classList.add('hello');
return element;
}
document.body.appendChild(component());
在运行npm run build后打包会失败,报错信息如下,意思是在解析到./src/index.css时模块解析失败,你可能需要适当的加载程序来处理此文件类型,目前没有配置加载程序来处理此文件。
ERROR in ./src/index.css 1:0
Module parse failed: Unexpected token (1:0)
You may need an appropriate loader to handle this file type,
currently no loaders are configured to process this file.
See https://webpack.js.org/concepts#loaders
> .hello {
| color: red;
| }
@ ./src/index.js 2:0-20
在开头我们已经说了原因,在这里我们就遇到了,来配置一下。先执行npm install --save-dev style-loader css-loader来安装我们所需要的依赖,然后在webpack.config.js中进行如下配置,再执行打包命令后成功,就没有了报错。
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
filename: 'main.js',
path: path.resolve(__dirname, 'dist'),
},
module: {
rules: [
{
test: /.css$/i,
use: ["style-loader", "css-loader"]
}
]
}
}
模块 loader 可以链式调用。链中的每个 loader 都将对资源进行转换。链会逆序执行。第一个 loader 将其结果(被转换后的资源)传递给下一个 loader,依此类推。最后,webpack 期望链中的最后的 loader 返回 JavaScript。
应保证 loader 的先后顺序:'style-loader' 在前,而 'css-loader' 在后。如果不遵守此约定,webpack 可能会抛出错误。
webpack 根据正则表达式,来确定应该查找哪些文件,并将其提供给指定的 loader。在这个示例中,所有以 .css 结尾的文件,都将被提供给 style-loader 和 css-loader。这使你可以在依赖于此样式的 js 文件中 import './style.css'。现在,在此模块执行过程中,含有 CSS 字符串的 <style> 标签,将被插入到 html 文件的 <head> 中。
images 图像和font字体篇
除了css文件外我们还会使用图片或者背景图,需要处理这些静态资源,同样也需要进行配置,如下:
module: {
rules: [
{
test: /.(png|svg|jpg|jpeg|gif)$/i,
type: 'asset/resource',
},
{
test: /.(woff|woff2|eot|ttf|otf)$/i,
type: 'asset/resource',
},
],
}
在webpack5中内置了 Asset Modules,我们可以轻松地将这些内容混入我们的系统中。在webpack4的时候使用file-loader,在遇到import Icon from './01.png';时,此图像会被处理并添加到 output 目录,并且 Icon 变量将包含该图像在处理后的最终 url。
使用 Asset Modules 可以接收并加载任何文件,然后将其输出到构建目录。所以我们的字体文件、其他资源文件等也可以通过它进行处理,添加一条规则就好了。例子可以看官网
plugin篇
插件 也是 webpack 的 重要功能。Webpack 自身也是构建于你在 webpack 配置中用到的 相同的插件系统 之上!插件目的在于解决 loader 无法实现的其他事。Webpack 提供很多开箱即用的 插件。
由于插件可以携带参数/选项,你必须在 webpack 配置中,向 plugins 属性传入一个 new 实例。取决于你的 webpack 用法,对应有多种使用插件的方式。这里以html-webpack-plugin插件为例,该插件会默认生成它自己的 index.html 文件,然后将所有的 bundle 会自动添加到 html 中并输出到dist目录下,不需要我们在像之前手动管理dist/index.html的资源引入问题了。在module.exports添加以下属性即可。
plugins: [
new HtmlWebpackPlugin({
title: '管理输出',
}),
],
开发环境
source map
在开发过程中,我们代码报错后很难定位到在原文件中的位置,比如我们把a.js b.js c.js打包到一个bundle.js后,要是其中一个文件报错了,控制台报错信息只能追踪到bundle.js,你可能需要准确地知道错误来自于哪个源文件,所以这种提示这通常不会提供太多帮助。因此webpack就提供了source map的功能,可以将编译后的代码映射回原始源代码。使用方法如下,在webpack.config.js中加入如下属性就好了。
devtool: 'inline-source-map',
devtool还有很多属性,不同的值会明显影响到构建(build)和重新构建(rebuild)的速度。可以看官网:webpack.docschina.org/configurati…
webpack-dev-server
在编写代码过程,我们改变一个文件后需要重新打包,然后浏览器打开,不是很麻烦吗?有没有保存代码后页面自动更新成最新代码的方案呢?当然是有,就是我们要说的webpack-dev-server。
webpack-dev-server 为你提供了一个基本的 web server,并且具有 live reloading(实时重新加载) 功能。设置如下:
安装webpack-dev-server: npm install --save-dev webpack-dev-server
然后添加配置如下:
devServer: {
static: './dist',
},
上面这些配置告知 webpack-dev-server,将 dist 目录下的文件 serve 到 localhost:8080 下。
在package.json中加入命令 "start": "webpack serve --open",运行命令后我们的dev-server就启好了,就实现了我们上面的需求。
webpack-dev-server在编译之后不会写入到任何输出文件,而是将文件存在內存中,然后将它们 serve 到 server 中,就好像它们是挂载在 server 根路径上的真实文件一样。
在webpack-dev-server中还可以配置其他属性,如port、publicPath、hot等。