開發一個webapck v3 的 loader

Github地址

github.com/CodeLittleP…css

前言

有時候,市面上的webpack loader並不徹底符合咱們的需求,因此,咱們不得不本身從0開始寫一個,或者是在別人寫的loader基礎之上進行修改。html

不管哪一種,都須要咱們對webpack加載loader的方式有所瞭解。node

說點題外話,不知道爲何webpack官網對loader的介紹那麼簡短,很難單單根據文檔就寫出loader來。因此還建議看些別人寫的loader,如babel-loader等。 好了,開始吧!webpack

實現

出招吧~git

在github上建立項目

建立本地項目

一、git clone項目到本地 二、初始化npmgithub

npm init
複製代碼

填寫完npm init的一路提示下來之後,咱們看下文件結構:web

.
├── README.md
└── package.json
複製代碼

三、安裝webpackshell

npm i -D webpack
複製代碼

四、設置一下package.json裏的scripts命令:npm

"scripts": {
  "dev": "webpack"
},
複製代碼

這樣的話,基本的工具就準備完畢了。json

編寫webpack.config.js

一、建立webpack.config.js

.
├── README.md
├── node_modules
├── package-lock.json
├── package.json
└── webpack.config.js
複製代碼

二、編輯webpack.config.js

const path = require('path')

module.exports = {
  entry: {
    app: path.resolve('demo/index.js')
  },
  output: {
    path: path.resolve('dist'),
    filename: 'index.js'
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        loader: path.resolve('src/loader-test.js'),
        options: {
          speak: 'wang~',
        }
      }
    ]
  }
}
複製代碼

由於咱們是從0開始編寫的,因此不得不先從簡單到複雜。 因此,如上,咱們經過path引用的方式來使用loader。而且,咱們配置了option,做爲參數。 index則是須要處理的文件。

編寫index.js

const cat = 'kitty'
console.log(cat)
複製代碼

編寫loader-test.js

// loader-utils做爲工具類引入(做爲webpack依賴,因此在安裝webpack時候就帶上了)
const loaderUtils = require('loader-utils')

// loader調用的時候,會將源數據和sourcemap做爲參數傳入函數
module.exports = function(source, inputSourceMap) {
  const code = source
  const map = inputSourceMap
  // loaderUtils.getOptions 能夠獲取到設置loader時候設置的options
  // 固然loaderUtils還有不少其餘有用的方法,詳情能夠看 https://github.com/webpack/loader-utils
  const loaderOptions = loaderUtils.getOptions(this) || {};
  console.log(source)
  console.log(loaderOptions)
  // loader須要將本身的值傳給下一個loader,而且,loader難免會有異步操做
  // 所以須要回調來證實本身已經處理結束了
  this.callback(null, code, map)
}
複製代碼

先看下目錄結構,爲了避免影響視覺,我忽略了node_module文件:

.
├── README.md
├── demo
│   └── index.js
├── package-lock.json
├── package.json
├── src
│   └── loader-test.js
└── webpack.config.js
複製代碼

好,讓咱們運行一下webpack,看一下效果: npm run dev

...
const cat = 'kitty'
console.log(cat)
{ speak: 'wang~' }
...
複製代碼

正如咱們寫的loader,打印出了index.js的源碼,以及,webpack.config.js配置loader時候的options。 是否是有點兒小興奮?

寫點有意義的功能

雖說是教程,可是這樣的小例子的確有點太過簡單了,咱們能夠作點有意義點的功能。 好比,咱們想把js中px所有替換成vw,比例就按照1vw = 10px吧。 (我相信不少朋友會以爲爲啥替換js,而不是css或者scss。由於,會涉及更多的webapck配置,比較無聊和對本章內容沒什麼做用,因此,我以爲仍是越簡單越好,就拿js舉例子吧) 好,計劃有了,開始行動吧!

從新編輯index.js

const parentStyle = ` background: #fdc; width: 1200px; height: 600px; box-sizing: border-box; padding: 150px 300px; `
const childStyle = ` background: #cdf; width: 600px; height: 300px; `
const parent = document.getElementById('parent')
const child = document.getElementById('child')
parent.style.cssText = parentStyle
child.style.cssText = childStyle
複製代碼

爲了更好展現,咱們再寫個html吧

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <style> * {padding: 0; margin: 0;} </style>
</head>
<body>
  <div id="parent">
    <div id="child"></div>
  </div>
</body>
</html>
複製代碼

讓啓動demo更順暢

一不作二不休,爲了更順暢的看效果,咱們加個webpack-dev-server自動啓動吧。同時,順帶着,將html-webpack-plugin和clean-webpack-plugin也都加上。 關於寫demo,我以爲,是寫npm modules必需要有的東西,若是沒有demo,沒有順暢的啓動demo操做。別說別人懶得看,本身都懶得啓動了。 好,咱們再看下如今的webpack配置:

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const CleanWebpackPlugin = require('clean-webpack-plugin')

module.exports = {
  entry: {
    app: path.resolve('demo/index.js')
  },
  output: {
    path: path.resolve('dist'),
    filename: 'index.js'
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        loader: path.resolve('src/loader-test.js')
      }
    ]
  },
  plugins: [
    // 清理dist
    new CleanWebpackPlugin('dist'),
    // 將js打入html
    new HtmlWebpackPlugin({
      filename: 'index.html',
      template: path.resolve('demo/index.html'),
      chunks: ['app'] // 由於只有一個頁面,這行不寫也能夠
    })
  ]
}
複製代碼

修改下package.json裏的scripts命令:

"scripts": {
  "dev": "webpack-dev-server --open"
},
複製代碼

而後,啓動實驗一下,npm run dev。 看下效果: 沒問題,進入下一步~

正式修改loader

讓咱們從新編輯loader-test.js吧:

...
  // 替換px
  const regex = /(\d+?)px/g
  code = code.replace(regex, function(match, p1) {
    return p1/10 + 'vw'
  })
  ...
}

複製代碼

而後,再從新啓動一下,咱們會發現,px都被替換成了vw了,並且比例爲1vw = 10px,成功! 固然,有同窗確定會想到,要是這個比例能夠本身設置那就更好了。實現方式固然也很簡單啊,還記得咱們以前是怎麼獲取loader中options配置的speak嗎?我相信同窗徹底能夠獨立完成了。

怎麼把包作成npm module,而後發到npm 上,之後都能用呢?

這個的話,實際上是我以前已經寫過這樣的文章了,同窗們能夠轉到npm-從0開始寫一個npm module

本文項目地址

沒錯~點我>>

最後,但願喜歡的同窗能給star哦

相關文章
相關標籤/搜索