手寫,發佈並調試webpack-loader

webpackloaderplugin爲咱們提供了強大的功能,下面咱們就簡單的實現一下webpack-loader,順便發佈到npm,以及使用npm link本地調試咱們的模塊。javascript

實現loader

這個loader的主要做用就是在打包出來的bundle文件裏插入一段自定義信息,上代碼java

// 新建一個項目
mkdir bundle-author-loader

npm init -y

npm install webpack webpack-cli --save-dev
複製代碼

根目錄新建webpack配置文件node

// webpack.config.js
const path = require("path");

module.exports = {
  mode: "development",
  entry: "./src/index.js",
  output: {
    filename: "bundle.js",
    path: path.resolve(__dirname, "dist"),
  },
  // 從node_modules以及loaders文件夾下加載loader,方便咱們調試
  resolveLoader: {
    modules: ["node_modules", path.resolve(__dirname, "loaders")],
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        use: [
          // 全部的js文件都將加載這個loader,而且有個text的配置項
          {
            loader: "bundle-author-loader",
            options: { text: "/*** author hsky ***/" },
          },
        ],
      },
    ],
  },
};

複製代碼

根目錄新建loaders文件夾webpack

// bundle-author-loader.js

// 校驗loader傳入的options
const { validate } = require("schema-utils");

// loader options的校驗規則
// options是一個object類型,有一個text屬性,這屬性是string類型
const schema = {
  type: "object",
  properties: {
    text: {
      type: "string",
    },
  },
};

module.exports = function (source) {
  // 獲取到用戶給當前 loader 傳入的 options
  // webpack v5 內置了這個方法,以前須要loader-utils這個包
  const options = this.getOptions();
  // 對loader傳入的options作校驗
  validate(schema, options, "bundle-author-loader");
  // 將咱們傳入的信息插入到source中
  return `${options.text} ${source}`;
};

複製代碼

而後咱們就能夠愉快的測試了,新建一個src文件夾web

// index.js
const a = 134
複製代碼

package.json中的script添加"build": "webpack",跑一下npm run build,此時的項目結構爲npm

bundle-author-loader
|-- dist
|	|-- bundle.js
|-- loaders
|	|-- bundle-author-loader.js
|-- node_modules
|-- src
|	|-- index.js
|-- package-lock.json
|-- package.json
|-- webpackage.config.js
複製代碼

dist文件夾下的bundle.js就是咱們打包出來的代碼啦,瞅一眼json

/* * ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development"). * This devtool is neither made for production nor for readable output files. * It uses "eval()" calls to create a separate source file in the browser devtools. * If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/) * or disable the default devtool with "devtool: false". * If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/). */
/******/ (() => { // webpackBootstrap
/*!**********************!*\ !*** ./src/index.js ***! \**********************/
eval("/*** author hsky ***/ const a = 1234;\n\n\n//# sourceURL=webpack://bundle-author-loader/./src/index.js?");
/******/ })()
;
複製代碼

咱們能夠看到咱們在loader中配置的options已經被打包進去了markdown

發佈到npm

// 輸入帳號密碼,沒有的自行去npm官網註冊
npm login 
複製代碼

發佈前須要整理一下咱們的代碼,只保留bundle-author-loader.jspackage.json,由於loader的默認規則,因此咱們把bundle-author-loader.js重命名爲index.js並補全一下package.json文件的信息,此時的文件目錄結構爲:測試

bundle-author-loader
|-- index.js
|-- package.json
複製代碼

在生產環境中,devDependencies最好改爲peerDependencies,避免與主項目的版本衝突ui

搞好準備工做,咱們開始發佈

// 輸入帳號密碼,沒有的自行去npm官網註冊
npm publish
複製代碼

若是出現403,可能的緣由:

  • 沒有在剛纔註冊的郵箱驗證
  • 使用了淘寶鏡像地址

若是出現404,可能須要npm adduser --scope

而後咱們就能在npm裏看到咱們的包了

如何調試

咱們新建一個項目,安裝一下咱們剛發佈的包

npm install bundle-author-loader --save-dev
複製代碼

和剛纔同樣配置一下webpack.config.js,由於咱們再也不須要本地調試,因此也再也不須要resolveLoader

const path = require("path");

module.exports = {
  mode: "development",
  entry: "./src/index.js",
  output: {
    filename: "bundle.js",
    path: path.resolve(__dirname, "dist"),
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        use: [
          {
            loader: "bundle-author-loader",
            options: { text: "/*** author hsky ***/" },
          },
        ],
      },
    ],
  },
};

複製代碼

跑一下npm run build,能夠看到,咱們的配置信息成功的打到了bundle文件裏

/* * ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development"). * This devtool is neither made for production nor for readable output files. * It uses "eval()" calls to create a separate source file in the browser devtools. * If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/) * or disable the default devtool with "devtool: false". * If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/). */
/******/ (() => { // webpackBootstrap
/*!**********************!*\ !*** ./src/index.js ***! \**********************/
eval("/*** author hsky ***/ const ab = 123456;\n\n\n//# sourceURL=webpack://webpack-loader/./src/index.js?");
/******/ })()
;
複製代碼

若是咱們後續對這個loader進行更新維護的話,就須要本地調試,這裏提供一種本地調試的方法npm link 咱們在bundle-author-loader(即咱們發佈到npm的項目)中,執行

npm link
複製代碼

注:若是用的是peerDependencies,則須要手動安裝一下依賴的包

咱們注意到,npm link會把咱們本地的包生成一個全局的軟連接,而後進入到另外一個項目(即便用bundle-author-loader的包),執行

npm link bundle-author-loader
複製代碼

此時,咱們能夠發現node_modules下面咱們沒有安裝bundle-author-loader,可是這個包卻出現了,這說明咱們已經成功創建兩個項目的連接,接下來就能夠愉快的調試項目了(使用方式和npm install的同樣)。 好比咱們在bundle-author-loader中想添加打包時的時間

// index.js

const { validate } = require("schema-utils");

const schema = {
  type: "object",
  properties: {
    text: {
      type: "string",
    },
  },
};

module.exports = function (source) {
  const options = this.getOptions();
  validate(schema, options, "bundle-author-loader");
  return `${options.text} /**** bundled at ${new Date()} ****/ ${source}`;
};

複製代碼

在測試項目中,直接執行npm run build,此時,打包後文件已是咱們想要調試的內容了

/* * ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development"). * This devtool is neither made for production nor for readable output files. * It uses "eval()" calls to create a separate source file in the browser devtools. * If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/) * or disable the default devtool with "devtool: false". * If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/). */
/******/ (() => { // webpackBootstrap
/*!**********************!*\ !*** ./src/index.js ***! \**********************/
eval("/*** author hsky ***/ /**** bundled at Mon Jan 25 2021 20:22:05 GMT+0800 (China Standard Time) ****/ const ab = 123456;\n\n\n//# sourceURL=webpack://webpack-loader/./src/index.js?");
/******/ })()
;
複製代碼

解除link狀態,在項目和模塊或者loader中 npm unlink xxx

大功告成!!!

相關文章
相關標籤/搜索