小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
关于 webpack loader
在学习 webpack
的过程中,避免不了要与 loader
、plugin
打交道,而手写一个自定义的 loader
或是 plugin
,则是检验自己学习成果的最好的方式之一。
那么接下来就来手写一个简单的 markdown-loader
吧!
初始化项目
创建文件
- 首先,需要初始化我们的项目,包含
html
、和main.ts
文件,并用webpack
进行相关配置。
package.json
:
{
"name": "webpack-loader-demo-1",
"version": "1.0.0",
"license": "MIT",
"dependencies": {
"@babel/core": "7.12.3",
"@babel/generator": "7.12.5",
"@babel/parser": "7.12.5",
"@babel/preset-env": "7.12.1",
"@babel/traverse": "7.12.5",
"@types/babel__traverse": "7.0.15",
"html-loader": "^2.1.2",
"html-webpack-plugin": "^5.4.0",
"marked": "^3.0.7",
"shelljs": "0.8.4",
"ts-node": "9.0.0",
"typescript": "4.0.5",
"webpack": "^5.59.0"
},
"devDependencies": {
"@types/babel__core": "7.1.12",
"@types/babel__generator": "7.6.2",
"@types/babel__parser": "7.1.1",
"@types/babel__preset-env": "7.9.1",
"@types/node": "14.14.6",
"@types/shelljs": "0.8.8",
"babel-loader": "^8.2.2",
"ts-loader": "^9.2.6",
"webpack-cli": "^4.9.1"
}
}
webpack.config.js
:
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const rootDir = process.cwd()
module.exports = {
mode: 'production',
entry: './src/main.ts',
output: {
filename: 'bundle.js',
path: path.join(__dirname, 'dist'),
},
module: {
rules: [
{
test: /.(ts|tsx)$/,
use: [
'babel-loader',
{
loader: 'ts-loader',
options: {
happyPackMode: true,
transpileOnly: true,
},
},
],
exclude: /node_modules/,
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(rootDir, 'public/index.html'),
inject: 'body',
scriptLoading: 'blocking',
minify: {
removeComments: true, //移除HTML中的注释
collapseWhitespace: true, //删除空白符与换行符
},
})
]
}
通过 yarn install
安装相关依赖
创建入口文件
在根目录下创建 public/index.html
文件,写入:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
</body>
</html>
在根目录下创建 src/main.ts
和 src/README.md
文件
// src/main.ts
import readme from './README.md'
const div = document.createElement('div')
div.innerHTML = readme
document.body.appendChild(div)
// src/README.md
# Hello
测试 markdown-loader
# Hi
这里是第二行
到这里,准备工作已经全部完成,接下来就让我们来写我们的 loader
吧!
开始写 loader!
编写 markdown-loader.js
- 在根目录创建
markdown-loader.js
文件:
function transform (source) {
const html = 'test'
return `export default ${JSON.stringify(html)}`; // webpack 官网推荐写法
}
module.exports = transform
- 在
webpack.config.js
中使用我们的loader
module.exports = {
//...
module: {
rules: [
//...
{
test: /.md$/,// 匹配入口文件中加载到的md文件
use: [
'./markdown-loader'
]
}
]
}
}
第一次测试
运行 yarn build
,并打开 dist
目录下的 index.html
文件,查看内容
可以看到,页面中正是我们写入的
test
的字符串
使用 marked 来转换字符串
yarn add marked
//markdown-loader.js
const marked = require('marked')
function transform (source) {
const html = marked(source)
return `export default ${JSON.stringify(html)}`;
}
module.exports = transform
第四次测试
运行 yarn build
,并打开 dist
目录下的 index.html
文件,查看内容
完成目标!
总结
webpack
的loader
本质就是把不是 JS 的内容,包装成能运行的 export default ${JSON.stringify(text)}
形式的 JS 代码