目录

上节: css代码分割

目录:

先改一下src/index.js:

import _ from 'lodash';const root = document.getElementById('root');root.innerText = _.join(['hello', 'webpack'], '-');

现在写一个简单的loader,将所有的webpack替换成其它内容,内容可通过options配置。
在根目录新建loaders/replace-loader.js。

loaders/replace-loader.js:

const { getOptions } = require('loader-utils');module.exports = function(source) {  /*     this指向webpack    source:打包后的文件内容    this.query options参数  */ const options = getOptions(this) || {}; // 返回处理后的结果,相当于是打包拦截器 return source.replace('webpack', options.name || 'Madao');}

source是打包后生成的文件,options可以拿到配置参数,这个loader会将所有webpack替换成options.name的内容,如果没指定options.name, 就替换成Madao.

然后引用这个loader, 修改webpack/webpack.base.js:

const HtmlWebpackPlugin = require('html-webpack-plugin');const { resolve } = require('path');module.exports = {  entry: './src/index.js',  output: {    path: resolve(__dirname, '../bundles')  },  // 注册loader  resolveLoader: {    // loader查找顺序,从左到右    modules: ['node_modules', './loaders/']  },  module: {    rules: [{      test: /\.js$/,      exclude: /node_modules/,            // 先不传options      use: ['replace-loader', 'babel-loader']    }, {      test: /\.(gif|jpg|jpeg|png|svg)$/,      use: ['url-loader']    }]  },  plugins: [    new HtmlWebpackPlugin({      template: './index.html'    })  ]};

安装loader工具库:npm i loader-utils -D
然后npm run build, 打开bundles下的main.[contenthash].js文件,应该可以搜索到Madao:

然后我们自己传一个配置参数,修改webpack/webpack.base.js:

// 省略module: {    rules: [{      test: /\.js$/,      exclude: /node_modules/,      use: [{        loader: 'replace-loader',        options: {          name: '史珍香'        }      }, 'babel-loader']    }, {      test: /\.(gif|jpg|jpeg|png|svg)$/,      use: ['url-loader']    }]  },// 省略

再次npm run build,可以看到webpack就换成了'史珍香':

一个简单的loader就实现了。现在这个replace-loader只返回了替换后的内容,如果还想返回点其它内容,就得再改写下。
loaders/replace-loader.js:

const { getOptions } = require('loader-utils');module.exports = function(source) {  /*     this指向webpack    source:打包后的文件内容    this.query options参数  */ const options = getOptions(this) || {}; // 返回处理后的结果,相当于是打包拦截器//  return source.replace('webpack', options.name || 'Madao'); const result = source.replace('webpack', options.name || 'Madao'); /*  this.callback(  err: Error | null,  // error信息  content: string | Buffer,   // 要返回的内容  sourceMap?: SourceMap,    // source-map  meta?: any  // 会被 webpack 忽略,可以是任何东西(例如一些元数据)。); */// 如果只传这两个参数,效果同上  this.callback(null, result);}

如果转换过程中有什么异步操作,还可以返回异步loader,这里用定时器模拟下异步
loaders/replace-loader.js:

module.exports = function(source) {  const callback = this.async();  setTimeout(() => {  // 直接影响打包时间    const options = getOptions(this);    const result = source.replace('webpack', options.name || 'Madao');    callback(null, result); // 这里实际还是调用了this.callback()  }, 3000);}

this对象上还挂了很多属性,具体参考:https://webpack.js.org/api/lo...

下节:编写一个plugin