参考:
loader入门
格式
Webpack中loader是一个CommonJs风格的函数,接收输入的源码,通过同步或异步的方式替换源码后进行输出。
module.exports = function(source, sourceMap, meta) { } source是输入的内容 sourceMap是可选的 meta是模块的元数据,也是可选的
该导出函数必须使用function,不能使用箭头函数,因为loader编写过程中会经常使用到this
访问选项和其他方法。
loader的配置文件
babel-loader在使用时可以加载.babelrc配置文件来配置plugins和presets,减少了webpack.config.js的代码量,便于维护。
流程
1,执行npm初始化,并安装webpack
npm init -y
npm install webpack webpack-cli
2,构建项目目录
|----loader # loader目录 |----replace-loader.js # 替换字符串的Loader |----src # 应用源码 |----index.js # 首页 |----package.json |----webpack.config.js
3,编写loader代码
module.exports = function(source) { return source.replace(/World/g, ‘Loader‘); };
4,配置webpack :webpack.config.js
const path = require(‘path‘); module.exports = { entry: ‘./src/index‘, target: ‘node‘, // 我们编译为Node.js环境下的JS,等下直接使用Node.js执行编译完成的文件 output:{ path: path.resolve(__dirname, ‘build‘), filename: ‘[name].js‘ }, module:{ rules:[ { test:/\.js$/, use: ‘replace-loader‘ } ] }, resolveLoader: { modules: [‘./node_modules‘, ‘./loader‘] // 配置loader的查找目录 } };
5,配置package脚本和执行
//编写package.json { "scripts":{ "build":"webpack" } } //构建打包 npm run build //构建完成后,执行 build/main.js
loader的选项
在Loader编写时,Webpack中官方推荐通过loader-utils来读取配置选项,我们需要先安装。
npm install loader-utils
给上文创建的loader传递选项:replace-loader.js
const loaderUtils = require(‘loader-utils‘); module.exports = function(source) { const options = loaderUtils.getOptions(this); return source.replace(/World/g, options.text); };
编辑webpack.config.js,给replace-loader传递选项
module.exports = { module:{ rules:[ { test:/\.js$/, use:[ { loader:‘replace-loader‘, options:{ text: ‘Webpack4‘, plugins:[], presets:[] } } ] } ] }, resolveLoader:{ modules: [‘./node_modules‘, ‘./loader‘] } };
异步loader
在Loader中,如果存在异步调用,那么就无法直接通过return返回构建后的结果了,此时需要使用到Webpack提供的回调函数将数据进行回调。
Webpack4给Loader提供了this.async()
函数,调用之后返回一个callback,callback的参数如下:
function callback( err: Error|null, content: string|Buffer, sourceMap?:SourceMap, meta?: any )
相应代码
module.exports = function(source) { const callback = this.async(); const output = source.replace(/World/g, ‘Webpack4‘); callback(null, output); }
raw式loader
module.exports = function(source) { assert(source instanceof Buffer); return someSyncOperation(source); }; module.exports.raw = true; // 设置当前Loader为raw loader, webpack会将原始的Buffer对象传入
综合例子:i18n-loader
目录结构
|----loader |----i18n-loader.js # loader |----i18n |----zh.json # 中文语言包 |----src |----index.js # 入口文件 |----webpack.config.js
相关配置文件
//i18n/zh.json
{
"hello": "你好",
"today": "今天"
}
//src/index.js
console.log(‘{{Hello}}, {{Today}} is a good day.‘);
loader/i18n-loader.js
const loaderUtils = require(‘loader-utils‘); const path = require(‘path‘); module.exports = function (source) { const options = loaderUtils.getOptions(this); const locale = options ? options.locale : null; // 读取语言配置文件 let json = null; if (locale) { const filename = path.resolve(__dirname, ‘..‘, ‘i18n‘, `${locale}.json`); json = require(filename); } // 读取语言标记 {{}} const matches = source.match(/\{\{\w+\}\}/g); for (const match of matches) { const name = match.match(/\{\{(\w+)\}\}/)[1].toLowerCase(); if (json !== null && json[name] !== undefined) { source = source.replace(match, json[name]); } else { source = source.replace(match, name); } } return source; }
构建
npm run build
build/main.js输出为
你好, 今天 is a good day.