首先创建一个文件夹,并执行npm init -y
mkdir my-loader
cd my-loader
npm init -y
这样就生成了package.json
{
"name": "my-loader",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
然后安装webpack webpack-cli
npm install webpack webpack-cli --save-dev
接下来创建src目录,并创建index.js文件
// src/index.js
console.log('Hello Huan');
再创建配置文件
// webpack.config.js
const path = require('path');
module.exports = {
entry: {
main: './src/index.js'
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js'
}
}
修改package.json
"scripts": {
"build": "webpack"
},
然后执行
npm run build
此时在控制台会看到如下提示
WARNING in configuration
The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment.
You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/configuration/mode/
我们需要在webpack.config.js中加上mode配置
// webpack.config.js
const path = require('path');
module.exports = {
mode: 'development',
entry: {
main: './src/index.js'
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js'
}
}
然后再执行
npm run build
在dist目录中生成了main.js,在文件末尾便能看到打包后的业务代码
/***/ "./src/index.js":
/*!**********************!*\
!*** ./src/index.js ***!
\**********************/
/*! no static exports found */
/***/ (function(module, exports) {
eval("console.log('Hello webpack');\n\n//# sourceURL=webpack:///./src/index.js?");
/***/ })
/******/ });
现在我们想在加载index.js时,将Huan替换为HuanLiu,这时就需要写一个loader来做这个事情
创建如下文件
// loaders/replaceLoader.js
module.exports = function (resource) {
return resource.replace('Huan', 'HuanLiu');
}
注意上面的函数不能写成箭头函数,否则,在函数内部使用的this将不能调用到webpack的方法与属性。
然后在webpack.config.js中添加如下内容
// webpack.config.js
module.exports = {
...
module: {
rules: [
{
test: /\.js/,
use: [
path.resolve(__dirname, './loaders/replaceLoader.js')
]
}
]
}
}
然后执行打包
npm run build
再打开main.js,能看到Huan已经替换成了HuanLiu
eval("console.log('Hello HuanLiu');\n\n//# sourceURL=webpack:///./src/index.js?");
这样我们就实现了一个最简单的loader。
现在我们再做稍微复杂一点的配置
// webpack.config.js
module: {
rules: [
{
test: /\.js/,
use: [
{
loader: path.resolve(__dirname, './loaders/replaceLoader.js'),
options: {
name: 'liu'
}
}
]
}
]
}
修改replaceLoader.js
// loaders/replaceLoader.js
module.exports = function (resource) {
return resource.replace('Huan', this.query.name);
}
上述代码通过this.query就能获取到options中的属性
再执行打包npm run build,就能看到打包后的代码如下所示
eval("console.log('Hello liu');\n\n//# sourceURL=webpack:///./src/index.js?");
我们还可以通过官方推荐的loader-utils来获取webpack.config.js中配置的options属性 首先安装loader-utils
npm install loader-utils --save-dev
然后修改replaceLoader.js
const loadUtils = require('loader-utils');
module.exports = function (resource) {
const options = loadUtils.getOptions(this);
return resource.replace('Huan', options.name);
}
再执行打包npm run build,打包后的结果与前面一样
eval("console.log('Hello liu');\n\n//# sourceURL=webpack:///./src/index.js?");
loader还有很多Api可供我们使用
this.callback(
err: Error | null,
content: string | Buffer,
sourceMap?: SourceMap,
meta?: any
);
使用callback我们能传递更多信息给replaceLoader,我们这里只使用了前两个参数
const loadUtils = require('loader-utils');
module.exports = function (resource) {
const options = loadUtils.getOptions(this);
const result = resource.replace('Huan', options.name);
this.callback(null, result);
}
再执行打包npm run build,所得结果跟之前一样。
至此,我们就编写了一个简单的loader,并讲解了其中的一些配置。
在下一节我们将继续学习如何编写一个Loader的更深入些的内容。