webpack4.29.x成神之路(二十) 编写一个loader

目录css

上节: css代码分割html

目录:node

clipboard.png

先改一下src/index.js:webpack

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

如今写一个简单的loader,将全部的webpack替换成其它内容,内容可经过options配置。
在根目录新建loaders/replace-loader.js。web

loaders/replace-loader.js:npm

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.segmentfault

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

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:babel

clipboard.png

而后咱们本身传一个配置参数,修改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就换成了'史珍香':

clipboard.png

一个简单的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

相关文章
相关标签/搜索