有時候,市面上的webpack loader並不徹底符合咱們的需求,因此,咱們不得不本身從0開始寫一個,或者是在別人寫的loader基礎之上進行修改。html
不管哪一種,都須要咱們對webpack加載loader的方式有所瞭解。node
說點題外話,不知道爲何webpack官網對loader的介紹那麼簡短,很難單單根據文檔就寫出loader來。因此還建議看些別人寫的loader,如babel-loader等。 好了,開始吧!webpack
出招吧~git
一、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
.
├── 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則是須要處理的文件。
const cat = 'kitty'
console.log(cat)
複製代碼
// 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舉例子吧) 好,計劃有了,開始行動吧!
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
複製代碼
<!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>
複製代碼
一不作二不休,爲了更順暢的看效果,咱們加個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-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-從0開始寫一個npm module
最後,但願喜歡的同窗能給star哦