實現自定義 Webpack Loader

編寫自定義 loader

loader 能作什麼?

webpack loader 是用於編譯源文件爲目標文件,默認狀況,webpack 只能編譯打包 JavaScript 文件,其餘文件則須要特定 loader 進行加載,如:css

  • css 文件模塊,加載器爲 css-loader (配合 style-loader 或者 MiniCssExtractPlugin.loader)
  • less 文件模塊,加載器爲 less-loader (配合預處理其 less)
  • png|jpg|jpeg|gif|svg 圖片,加載器爲 url-loader, file-loader

執行順序

  • 執行順序爲從左到右(從下到上)
  • 導出 loader 函數,也可添加 patch 方法(相似 koa 的洋蔥模型)
    • 配置 loaders ['loader1', 'loader2']
    • 執行順序 loader1.patch => loader2.patch => loader2.loader => loader1.loader

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, 可配置別名,查找路徑node

webpack.config.jswebpack

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

banner-loader

爲代碼添加註釋,代表代碼版權,或者編寫人,時間等信息web

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

/** * 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,比較基礎,屬於入門級。less

相關文章
相關標籤/搜索