阅读 904

实现自定义 Webpack Loader

编写自定义 loader

loader 能做什么?

webpack loader 是用于编译源文件为目标文件,默认情况,webpack 只能编译打包 JavaScript 文件,其他文件则需要特定 loader 进行加载,如:

  • css 文件模块,加载器为 css-loader (配合 style-loader 或者 MiniCssExtractPlugin.loader)
  • less 文件模块,加载器为 less-loader (配合预处理其 less)
  • png|jpg|jpeg|gif|svg 图片,加载器为 url-loader, file-loader

执行顺序

  • 执行顺序为从左到右(从下到上)
  • 导出 loader 函数,也可添加 pitch 方法(类似 koa 的洋葱模型)
    • 配置 loaders ['loader1', 'loader2']
    • 执行顺序 loader1.pitch => loader2.pitch => loader2.pitch => loader1.pitch

babel-loader

简单实现 babel-loader 转译高级 JavaScript 语法 loaders/babel-loader

const babel = require('@babel/core');

function loader(source, inputSourceMap) {
  // 启用缓存 
  this.cacheable();
  // 供 webpack 调用
  const options = {
    presets: ['@babel/preset-env'],
    inputSourceMap,
    sourceMap: true,
    filename: this.request.split('!')[1].split('/').pop()
  };
  // this.request 数据格式
  // E:\\0-前端\\00-框架\\webpack\\源码学习\\webpack-source-analysis\\loaders\\babel-loader.js!E:\\0-前端\\00-框架\\webpack\\源码学习\\webpack-source-analysis\\src\\index.js
  let { code, map, ast }  = babel.transform(source, options);
  return this.callback(null, code, map, ast);
}

module.exports = loader;
复制代码

这里用到 webpack.config.resolveLoader,解析 loader, 可配置别名,查找路径

webpack.config.js

{
    resolveLoader: {
        alias: {
            'babel-loader': resolve('./loaders/babel-loader'),
        },
        modules: [ resolve('./loaders'), 'node_modules' ]
    },
    module: {
        rules: [
            { test: /\.js$/, use: 'babel-loader' }
        ]
    }
}
复制代码

banner-loader

为代码添加注释,表明代码版权,或者编写人,时间等信息

banner-loader.js

const babel = require('@babel/core');

function loader(source, inputSourceMap) {
  this.cacheable && this.cacheable();
  // 供 webpack 调用
  const options = {
    presets: ['@babel/preset-env'],
    inputSourceMap,
    sourceMap: true,
    filename: this.request.split('!')[1].split('/').pop()
  };
  // this.request 数据格式
  // E:\\0-前端\\00-框架\\webpack\\源码学习\\webpack-source-analysis\\loaders\\babel-loader.js!E:\\0-前端\\00-框架\\webpack\\源码学习\\webpack-source-analysis\\src\\index.js
  let { code, map, ast }  = babel.transform(source, options);
  return this.callback(null, code, map, ast);
}

module.exports = loader;
复制代码

bannder.js

/**
 * Copyright: Xiangju
 * Author: stella
 */
复制代码

webpack.config.js

{
 resolveLoader: {
    alias: {
      'babel-loader': resolve('./loaders/babel-loader'),
+     'banner-loader': resolve('./loaders/banner-loader'),
    },
  },
  module: {
    rules: [
      { test: /\.js$/, use: [
        {
          loader: 'banner-loader',
+         options: {
+           filename: resolve('./loaders/banner.js'),
+         }
        },
        'babel-loader',
      ] }
    ]
  },
}

复制代码

总结

以上实现的自定义 loader,比较基础,属于入门级。

文章分类
前端
文章标签