一、初始化一个webpack项目
二、src同级目录下新建loaders文件夹
新建markLoader.js
loader就是一个函数,注意不能写箭头函数,因为要使用this。
module.exports = function(source) {return source.replace('hello', 'helloword');}
webpack配置module: {rules: [{test: /\.js$/,exclude: /node_modules/,use: [// 不传参数path.resolve(__dirname, './loaders/markLoader.js')]}]}
三、loader如何接收webpack配置的参数
loader:module.exports = function(source) {console.log(this.query) // 通过this可以拿到配置中的参数console.log(this.query.name) // 拿到loader下options参数的配置return source.replace('hello', 'helloword');}
webpack.config.js:module: {rules: [{test: /\.js$/,exclude: /node_modules/,use: [{loader: path.resolve(__dirname, './loaders/markLoader.js'),options: { // 传递参数name:'helloword'}}]}]}
通过loader-utils来处理参数
loader:// 如果参数不好解析,可以使用loader-utilsconst loaderUtils = require('loader-utils');module.exports = function(source) {// console.log(this.query) // 通过this可以拿到配置中的参数const option = loaderUtils.getOptions(this)return source.replace('hello', option.name);}
通过schema-utils来验证参数
schema.json{"type": "object","properties": {"name": {"type": "string","description": "名称"}},"additionalProperties": true // 可以有多个,如果是false,json定义几个参数,外部只能传几个参数}
const { validate } = require('schema-utils')const schema = require('/schema');module.exports = function(source) {validate(schema, source, {name: 'lodaler1' // 报错的lodaler})}
四、loader中传递源代码的同时想要带参数
// this.callback()const loaderUtils = require('loader-utils');module.exports = function(source) {// console.log(this.query) // 通过this可以拿到配置中的参数const option = loaderUtils.getOptions(this)const result = source.replace('hello', option.name);this.callback(null, result);}// 此外 this.callbak还可以传递sourceMap等等
五、如何编写异步loader
const loaderUtils = require('loader-utils');module.exports = function(source) {const option = loaderUtils.getOptions(this)const callback = this.async();// this.async() 就是一个callbacksetTimeout(() => {const result = source.replace('hello', option.name);callback(null, result)}, 1000)}
六、多个loader配合使用
新建两个loader
webpack.config.js:module: {rules: [{test: /\.js$/,exclude: /node_modules/,// 新使用markLoader1进行处理,处理完成之后,交给markLoader2处理use: [{loader: path.resolve(__dirname, './loaders/markLoader2.js'),options: { // 传递参数name:'helloword'}},{loader: path.resolve(__dirname, './loaders/markLoader1.js'),options: { // 传递参数name:'helloword'}}]}]}
loader执行顺序
如果有多个loader,是把loader放在数组中,loader是从数组的后面开始执行loader上有个pitck方法,是从前向后执行
七、写loader的时候,去掉path.resolve
webpack.config.js:resolveLoader: {// 定义loader先去node_modules中查找,如果没有,就去自定义的loader文件夹下查找modules: ['node_modules', './loaders']},module: {rules: [{test: /\.js$/,exclude: /node_modules/,// 新使用markLoader1进行处理,处理完成之后,交给markLoader2处理use: [{loader: 'markLoader2',options: { // 传递参数name:'helloword'}},{loader: 'markLoader1',options: { // 传递参数name:'helloword'}}]}]}
八、项目中用到的自定义loader
1、jquery代码中添加异常捕获
如果一个一个在jq代码中添加异常捕获,这样太麻烦
可以使用loader
loader:const loaderUtils = require('loader-utils');module.exports = function(source) {// source就是源代码,拿到源代码之后,通过ast进行分析// 找到function,并对function进行处理// 将function都放在try-catch中执行try{function(){}}catch(e) {console.log(e)}}
2、网站国际化
loader:module.exports = function(source) {if (Node全局变量 == '中文'){source.repalce('{{title}}', '中文')}else {source.repalce('{{title}}', 'en')}}
