This commit is contained in:
taylor
2024-10-16 17:02:47 +08:00
commit dc507d2a0b
266 changed files with 62650 additions and 0 deletions

View File

@@ -0,0 +1,24 @@
export const data = {
"key": "v-2259a8b0",
"path": "/origin/",
"title": "介绍",
"lang": "zh-CN",
"frontmatter": {},
"excerpt": "",
"headers": [],
"git": {},
"filePathRelative": "origin/README.md"
}
if (import.meta.webpackHot) {
import.meta.webpackHot.accept()
if (__VUE_HMR_RUNTIME__.updatePageData) {
__VUE_HMR_RUNTIME__.updatePageData(data)
}
}
if (import.meta.hot) {
import.meta.hot.accept(({ data }) => {
__VUE_HMR_RUNTIME__.updatePageData(data)
})
}

View File

@@ -0,0 +1,9 @@
<template><h1 id="介绍" tabindex="-1"><a class="header-anchor" href="#介绍" aria-hidden="true">#</a> 介绍</h1>
<p>本章节我们主要学习</p>
<ul>
<li>loader 原理</li>
<li>自定义常用 loader</li>
<li>plugin 原理</li>
<li>自定义常用 plugin</li>
</ul>
</template>

View File

@@ -0,0 +1,123 @@
export const data = {
"key": "v-1cfd2df6",
"path": "/origin/loader.html",
"title": "Loader 原理",
"lang": "zh-CN",
"frontmatter": {},
"excerpt": "",
"headers": [
{
"level": 2,
"title": "loader 概念",
"slug": "loader-概念",
"children": []
},
{
"level": 2,
"title": "loader 执行顺序",
"slug": "loader-执行顺序",
"children": []
},
{
"level": 2,
"title": "开发一个 loader",
"slug": "开发一个-loader",
"children": [
{
"level": 3,
"title": "1. 最简单的 loader",
"slug": "_1-最简单的-loader",
"children": []
},
{
"level": 3,
"title": "2. loader 接受的参数",
"slug": "_2-loader-接受的参数",
"children": []
}
]
},
{
"level": 2,
"title": "loader 分类",
"slug": "loader-分类",
"children": [
{
"level": 3,
"title": "1. 同步 loader",
"slug": "_1-同步-loader",
"children": []
},
{
"level": 3,
"title": "2. 异步 loader",
"slug": "_2-异步-loader",
"children": []
},
{
"level": 3,
"title": "3. Raw Loader",
"slug": "_3-raw-loader",
"children": []
},
{
"level": 3,
"title": "4. Pitching Loader",
"slug": "_4-pitching-loader",
"children": []
}
]
},
{
"level": 2,
"title": "loader API",
"slug": "loader-api",
"children": []
},
{
"level": 2,
"title": "手写 clean-log-loader",
"slug": "手写-clean-log-loader",
"children": []
},
{
"level": 2,
"title": "手写 banner-loader",
"slug": "手写-banner-loader",
"children": []
},
{
"level": 2,
"title": "手写 babel-loader",
"slug": "手写-babel-loader",
"children": []
},
{
"level": 2,
"title": "手写 file-loader",
"slug": "手写-file-loader",
"children": []
},
{
"level": 2,
"title": "手写 style-loader",
"slug": "手写-style-loader",
"children": []
}
],
"git": {},
"filePathRelative": "origin/loader.md"
}
if (import.meta.webpackHot) {
import.meta.webpackHot.accept()
if (__VUE_HMR_RUNTIME__.updatePageData) {
__VUE_HMR_RUNTIME__.updatePageData(data)
}
}
if (import.meta.hot) {
import.meta.hot.accept(({ data }) => {
__VUE_HMR_RUNTIME__.updatePageData(data)
})
}

View File

@@ -0,0 +1,355 @@
<template><h1 id="loader-原理" tabindex="-1"><a class="header-anchor" href="#loader-原理" aria-hidden="true">#</a> Loader 原理</h1>
<h2 id="loader-概念" tabindex="-1"><a class="header-anchor" href="#loader-概念" aria-hidden="true">#</a> loader 概念</h2>
<p>帮助 webpack 将不同类型的文件转换为 webpack 可识别的模块</p>
<h2 id="loader-执行顺序" tabindex="-1"><a class="header-anchor" href="#loader-执行顺序" aria-hidden="true">#</a> loader 执行顺序</h2>
<ol>
<li>分类</li>
</ol>
<ul>
<li>pre 前置 loader</li>
<li>normal 普通 loader</li>
<li>inline 内联 loader</li>
<li>post 后置 loader</li>
</ul>
<ol start="2">
<li>执行顺序</li>
</ol>
<ul>
<li>4 loader 的执行优级为<code>pre &gt; normal &gt; inline &gt; post</code> </li>
<li>相同优先级的 loader 执行顺序为<code>从右到左从下到上</code></li>
</ul>
<p>例如</p>
<div class="language-javascript ext-js line-numbers-mode"><pre v-pre class="language-javascript"><code><span class="token comment">// 此时loader执行顺序loader3 - loader2 - loader1</span>
<span class="token literal-property property">module</span><span class="token operator">:</span> <span class="token punctuation">{</span>
<span class="token literal-property property">rules</span><span class="token operator">:</span> <span class="token punctuation">[</span>
<span class="token punctuation">{</span>
<span class="token literal-property property">test</span><span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.js$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
<span class="token literal-property property">loader</span><span class="token operator">:</span> <span class="token string">"loader1"</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">{</span>
<span class="token literal-property property">test</span><span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.js$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
<span class="token literal-property property">loader</span><span class="token operator">:</span> <span class="token string">"loader2"</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">{</span>
<span class="token literal-property property">test</span><span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.js$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
<span class="token literal-property property">loader</span><span class="token operator">:</span> <span class="token string">"loader3"</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br></div></div><div class="language-javascript ext-js line-numbers-mode"><pre v-pre class="language-javascript"><code><span class="token comment">// 此时loader执行顺序loader1 - loader2 - loader3</span>
<span class="token literal-property property">module</span><span class="token operator">:</span> <span class="token punctuation">{</span>
<span class="token literal-property property">rules</span><span class="token operator">:</span> <span class="token punctuation">[</span>
<span class="token punctuation">{</span>
<span class="token literal-property property">enforce</span><span class="token operator">:</span> <span class="token string">"pre"</span><span class="token punctuation">,</span>
<span class="token literal-property property">test</span><span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.js$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
<span class="token literal-property property">loader</span><span class="token operator">:</span> <span class="token string">"loader1"</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">{</span>
<span class="token comment">// 没有enforce就是normal</span>
<span class="token literal-property property">test</span><span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.js$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
<span class="token literal-property property">loader</span><span class="token operator">:</span> <span class="token string">"loader2"</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">{</span>
<span class="token literal-property property">enforce</span><span class="token operator">:</span> <span class="token string">"post"</span><span class="token punctuation">,</span>
<span class="token literal-property property">test</span><span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.js$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
<span class="token literal-property property">loader</span><span class="token operator">:</span> <span class="token string">"loader3"</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br></div></div><ol start="3">
<li>使用 loader 的方式</li>
</ol>
<ul>
<li>配置方式 <code>webpack.config.js</code> 文件中指定 loaderprenormalpost loader</li>
<li>内联方式在每个 <code>import</code> 语句中显式指定 loaderinline loader</li>
</ul>
<ol start="4">
<li>inline loader</li>
</ol>
<p>用法<code>import Styles from 'style-loader!css-loader?modules!./styles.css';</code></p>
<p>含义</p>
<ul>
<li>使用 <code>css-loader</code> <code>style-loader</code> 处理 <code>styles.css</code> 文件</li>
<li>通过 <code>!</code> 将资源中的 loader 分开</li>
</ul>
<p><code>inline loader</code> 可以通过添加不同前缀跳过其他类型 loader</p>
<ul>
<li><code>!</code> 跳过 normal loader</li>
</ul>
<p><code>import Styles from '!style-loader!css-loader?modules!./styles.css';</code></p>
<ul>
<li><code>-!</code> 跳过 pre normal loader</li>
</ul>
<p><code>import Styles from '-!style-loader!css-loader?modules!./styles.css';</code></p>
<ul>
<li><code>!!</code> 跳过 pre normal post loader</li>
</ul>
<p><code>import Styles from '!!style-loader!css-loader?modules!./styles.css';</code></p>
<h2 id="开发一个-loader" tabindex="-1"><a class="header-anchor" href="#开发一个-loader" aria-hidden="true">#</a> 开发一个 loader</h2>
<h3 id="_1-最简单的-loader" tabindex="-1"><a class="header-anchor" href="#_1-最简单的-loader" aria-hidden="true">#</a> 1. 最简单的 loader</h3>
<div class="language-javascript ext-js line-numbers-mode"><pre v-pre class="language-javascript"><code><span class="token comment">// loaders/loader1.js</span>
module<span class="token punctuation">.</span><span class="token function-variable function">exports</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token function">loader1</span><span class="token punctuation">(</span><span class="token parameter">content</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"hello loader"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> content<span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br></div></div><p>它接受要处理的源码作为参数输出转换后的 js 代码</p>
<h3 id="_2-loader-接受的参数" tabindex="-1"><a class="header-anchor" href="#_2-loader-接受的参数" aria-hidden="true">#</a> 2. loader 接受的参数</h3>
<ul>
<li><code>content</code> 源文件的内容</li>
<li><code>map</code> SourceMap 数据</li>
<li><code>meta</code> 数据可以是任何内容</li>
</ul>
<h2 id="loader-分类" tabindex="-1"><a class="header-anchor" href="#loader-分类" aria-hidden="true">#</a> loader 分类</h2>
<h3 id="_1-同步-loader" tabindex="-1"><a class="header-anchor" href="#_1-同步-loader" aria-hidden="true">#</a> 1. 同步 loader</h3>
<div class="language-javascript ext-js line-numbers-mode"><pre v-pre class="language-javascript"><code>module<span class="token punctuation">.</span><span class="token function-variable function">exports</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">content<span class="token punctuation">,</span> map<span class="token punctuation">,</span> meta</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> content<span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><p><code>this.callback</code> 方法则更灵活因为它允许传递多个参数而不仅仅是 <code>content</code></p>
<div class="language-javascript ext-js line-numbers-mode"><pre v-pre class="language-javascript"><code>module<span class="token punctuation">.</span><span class="token function-variable function">exports</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">content<span class="token punctuation">,</span> map<span class="token punctuation">,</span> meta</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// 传递map让source-map不中断</span>
<span class="token comment">// 传递meta让下一个loader接收到其他参数</span>
<span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">callback</span><span class="token punctuation">(</span><span class="token keyword">null</span><span class="token punctuation">,</span> content<span class="token punctuation">,</span> map<span class="token punctuation">,</span> meta<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span><span class="token punctuation">;</span> <span class="token comment">// 当调用 callback() 函数时,总是返回 undefined</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br></div></div><h3 id="_2-异步-loader" tabindex="-1"><a class="header-anchor" href="#_2-异步-loader" aria-hidden="true">#</a> 2. 异步 loader</h3>
<div class="language-javascript ext-js line-numbers-mode"><pre v-pre class="language-javascript"><code>module<span class="token punctuation">.</span><span class="token function-variable function">exports</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">content<span class="token punctuation">,</span> map<span class="token punctuation">,</span> meta</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> callback <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">async</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 进行异步操作</span>
<span class="token function">setTimeout</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token function">callback</span><span class="token punctuation">(</span><span class="token keyword">null</span><span class="token punctuation">,</span> result<span class="token punctuation">,</span> map<span class="token punctuation">,</span> meta<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br></div></div><blockquote>
<p>由于同步计算过于耗时 Node.js 这样的单线程环境下进行此操作并不是好的方案我们建议尽可能地使你的 loader 异步化但如果计算量很小同步 loader 也是可以的</p>
</blockquote>
<h3 id="_3-raw-loader" tabindex="-1"><a class="header-anchor" href="#_3-raw-loader" aria-hidden="true">#</a> 3. Raw Loader</h3>
<p>默认情况下资源文件会被转化为 UTF-8 字符串然后传给 loader通过设置 raw trueloader 可以接收原始的 Buffer</p>
<div class="language-javascript ext-js line-numbers-mode"><pre v-pre class="language-javascript"><code>module<span class="token punctuation">.</span><span class="token function-variable function">exports</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">content</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// content是一个Buffer数据</span>
<span class="token keyword">return</span> content<span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
module<span class="token punctuation">.</span>exports<span class="token punctuation">.</span>raw <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span> <span class="token comment">// 开启 Raw Loader</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br></div></div><h3 id="_4-pitching-loader" tabindex="-1"><a class="header-anchor" href="#_4-pitching-loader" aria-hidden="true">#</a> 4. Pitching Loader</h3>
<div class="language-javascript ext-js line-numbers-mode"><pre v-pre class="language-javascript"><code>module<span class="token punctuation">.</span><span class="token function-variable function">exports</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">content</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> content<span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
module<span class="token punctuation">.</span>exports<span class="token punctuation">.</span><span class="token function-variable function">pitch</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">remainingRequest<span class="token punctuation">,</span> precedingRequest<span class="token punctuation">,</span> data</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"do somethings"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br></div></div><p>webpack 会先从左到右执行 loader 链中的每个 loader 上的 pitch 方法如果有然后再从右到左执行 loader 链中的每个 loader 上的普通 loader 方法</p>
<p><img src="/imgs/source/loader1.png" alt="loader执行流程"></p>
<p>在这个过程中如果任何 pitch 有返回值 loader 链被阻断webpack 会跳过后面所有的的 pitch loader直接进入上一个 loader </p>
<p><img src="/imgs/source/loader2.png" alt="loader执行流程"></p>
<h2 id="loader-api" tabindex="-1"><a class="header-anchor" href="#loader-api" aria-hidden="true">#</a> loader API</h2>
<table>
<thead>
<tr>
<th>方法名</th>
<th>含义</th>
<th>用法</th>
</tr>
</thead>
<tbody>
<tr>
<td>this.async</td>
<td>异步回调 loader返回 this.callback</td>
<td>const callback = this.async()</td>
</tr>
<tr>
<td>this.callback</td>
<td>可以同步或者异步调用的并返回多个结果的函数</td>
<td>this.callback(err, content, sourceMap?, meta?)</td>
</tr>
<tr>
<td>this.getOptions(schema)</td>
<td>获取 loader options</td>
<td>this.getOptions(schema)</td>
</tr>
<tr>
<td>this.emitFile</td>
<td>产生一个文件</td>
<td>this.emitFile(name, content, sourceMap)</td>
</tr>
<tr>
<td>this.utils.contextify</td>
<td>返回一个相对路径</td>
<td>this.utils.contextify(context, request)</td>
</tr>
<tr>
<td>this.utils.absolutify</td>
<td>返回一个绝对路径</td>
<td>this.utils.absolutify(context, request)</td>
</tr>
</tbody>
</table>
<blockquote>
<p>更多文档请查阅 <a href="https://webpack.docschina.org/api/loaders/#the-loader-context" target="_blank" rel="noopener noreferrer">webpack 官方 loader api 文档<ExternalLinkIcon/></a></p>
</blockquote>
<h2 id="手写-clean-log-loader" tabindex="-1"><a class="header-anchor" href="#手写-clean-log-loader" aria-hidden="true">#</a> 手写 clean-log-loader</h2>
<p>作用用来清理 js 代码中的<code>console.log</code></p>
<div class="language-javascript ext-js line-numbers-mode"><pre v-pre class="language-javascript"><code><span class="token comment">// loaders/clean-log-loader.js</span>
module<span class="token punctuation">.</span><span class="token function-variable function">exports</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token function">cleanLogLoader</span><span class="token punctuation">(</span><span class="token parameter">content</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// 将console.log替换为空</span>
<span class="token keyword">return</span> content<span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">console\.log\(.*\);?</span><span class="token regex-delimiter">/</span><span class="token regex-flags">g</span></span><span class="token punctuation">,</span> <span class="token string">""</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br></div></div><h2 id="手写-banner-loader" tabindex="-1"><a class="header-anchor" href="#手写-banner-loader" aria-hidden="true">#</a> 手写 banner-loader</h2>
<p>作用 js 代码添加文本注释</p>
<ul>
<li>loaders/banner-loader/index.js</li>
</ul>
<div class="language-javascript ext-js line-numbers-mode"><pre v-pre class="language-javascript"><code><span class="token keyword">const</span> schema <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"./schema.json"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
module<span class="token punctuation">.</span><span class="token function-variable function">exports</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">content</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// 获取loader的options同时对options内容进行校验</span>
<span class="token comment">// schema是options的校验规则符合 JSON schema 规则)</span>
<span class="token keyword">const</span> options <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">getOptions</span><span class="token punctuation">(</span>schema<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> prefix <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">
/*
* Author: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>options<span class="token punctuation">.</span>author<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">
*/
</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>prefix<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> \n </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>content<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br></div></div><ul>
<li>loaders/banner-loader/schema.json</li>
</ul>
<div class="language-json ext-json line-numbers-mode"><pre v-pre class="language-json"><code><span class="token punctuation">{</span>
<span class="token property">"type"</span><span class="token operator">:</span> <span class="token string">"object"</span><span class="token punctuation">,</span>
<span class="token property">"properties"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
<span class="token property">"author"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
<span class="token property">"type"</span><span class="token operator">:</span> <span class="token string">"string"</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token property">"additionalProperties"</span><span class="token operator">:</span> <span class="token boolean">false</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br></div></div><h2 id="手写-babel-loader" tabindex="-1"><a class="header-anchor" href="#手写-babel-loader" aria-hidden="true">#</a> 手写 babel-loader</h2>
<p>作用编译 js 代码 ES6+语法编译成 ES5-语法</p>
<ul>
<li>下载依赖</li>
</ul>
<div class="language-text ext-text line-numbers-mode"><pre v-pre class="language-text"><code>npm i @babel/core @babel/preset-env -D
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br></div></div><ul>
<li>loaders/babel-loader/index.js</li>
</ul>
<div class="language-javascript ext-js line-numbers-mode"><pre v-pre class="language-javascript"><code><span class="token keyword">const</span> schema <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"./schema.json"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> babel <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"@babel/core"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
module<span class="token punctuation">.</span><span class="token function-variable function">exports</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">content</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> options <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">getOptions</span><span class="token punctuation">(</span>schema<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 使用异步loader</span>
<span class="token keyword">const</span> callback <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">async</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 使用babel对js代码进行编译</span>
babel<span class="token punctuation">.</span><span class="token function">transform</span><span class="token punctuation">(</span>content<span class="token punctuation">,</span> options<span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">err<span class="token punctuation">,</span> result</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">callback</span><span class="token punctuation">(</span>err<span class="token punctuation">,</span> result<span class="token punctuation">.</span>code<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br></div></div><ul>
<li>loaders/banner-loader/schema.json</li>
</ul>
<div class="language-json ext-json line-numbers-mode"><pre v-pre class="language-json"><code><span class="token punctuation">{</span>
<span class="token property">"type"</span><span class="token operator">:</span> <span class="token string">"object"</span><span class="token punctuation">,</span>
<span class="token property">"properties"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
<span class="token property">"presets"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
<span class="token property">"type"</span><span class="token operator">:</span> <span class="token string">"array"</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token property">"additionalProperties"</span><span class="token operator">:</span> <span class="token boolean">true</span>
<span class="token punctuation">}</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br></div></div><h2 id="手写-file-loader" tabindex="-1"><a class="header-anchor" href="#手写-file-loader" aria-hidden="true">#</a> 手写 file-loader</h2>
<p>作用将文件原封不动输出出去</p>
<ul>
<li>下载包</li>
</ul>
<div class="language-text ext-text line-numbers-mode"><pre v-pre class="language-text"><code>npm i loader-utils -D
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br></div></div><ul>
<li>loaders/file-loader.js</li>
</ul>
<div class="language-javascript ext-js line-numbers-mode"><pre v-pre class="language-javascript"><code><span class="token keyword">const</span> loaderUtils <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"loader-utils"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">function</span> <span class="token function">fileLoader</span><span class="token punctuation">(</span><span class="token parameter">content</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// 根据文件内容生产一个新的文件名称</span>
<span class="token keyword">const</span> filename <span class="token operator">=</span> loaderUtils<span class="token punctuation">.</span><span class="token function">interpolateName</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">,</span> <span class="token string">"[hash].[ext]"</span><span class="token punctuation">,</span> <span class="token punctuation">{</span>
content<span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 输出文件</span>
<span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">emitFile</span><span class="token punctuation">(</span>filename<span class="token punctuation">,</span> content<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 暴露出去给js引用。</span>
<span class="token comment">// 记得加上''</span>
<span class="token keyword">return</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">export default '</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>filename<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">'</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// loader 解决的是二进制的内容</span>
<span class="token comment">// 图片是 Buffer 数据</span>
fileLoader<span class="token punctuation">.</span>raw <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
module<span class="token punctuation">.</span>exports <span class="token operator">=</span> fileLoader<span class="token punctuation">;</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br></div></div><ul>
<li>loader 配置</li>
</ul>
<div class="language-javascript ext-js line-numbers-mode"><pre v-pre class="language-javascript"><code><span class="token punctuation">{</span>
<span class="token literal-property property">test</span><span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.(png|jpe?g|gif)$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
<span class="token literal-property property">loader</span><span class="token operator">:</span> <span class="token string">"./loaders/file-loader.js"</span><span class="token punctuation">,</span>
<span class="token literal-property property">type</span><span class="token operator">:</span> <span class="token string">"javascript/auto"</span><span class="token punctuation">,</span> <span class="token comment">// 解决图片重复打包问题</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br></div></div><h2 id="手写-style-loader" tabindex="-1"><a class="header-anchor" href="#手写-style-loader" aria-hidden="true">#</a> 手写 style-loader</h2>
<p>作用动态创建 style 标签插入 js 中的样式代码使样式生效</p>
<ul>
<li>loaders/style-loader.js</li>
</ul>
<div class="language-javascript ext-js line-numbers-mode"><pre v-pre class="language-javascript"><code><span class="token keyword">const</span> <span class="token function-variable function">styleLoader</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">;</span>
styleLoader<span class="token punctuation">.</span><span class="token function-variable function">pitch</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">remainingRequest</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">/*
remainingRequest: C:\Users\86176\Desktop\source\node_modules\css-loader\dist\cjs.js!C:\Users\86176\Desktop\source\src\css\index.css
这里是inline loader用法代表后面还有一个css-loader等待处理
最终我们需要将remainingRequest中的路径转化成相对路径webpack才能处理
希望得到:../../node_modules/css-loader/dist/cjs.js!./index.css
所以:需要将绝对路径转化成相对路径
要求:
1. 必须是相对路径
2. 相对路径必须以 ./ 或 ../ 开头
3. 相对路径的路径分隔符必须是 / ,不能是 \
*/</span>
<span class="token keyword">const</span> relativeRequest <span class="token operator">=</span> remainingRequest
<span class="token punctuation">.</span><span class="token function">split</span><span class="token punctuation">(</span><span class="token string">"!"</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">part</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token comment">// 将路径转化为相对路径</span>
<span class="token keyword">const</span> relativePath <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>utils<span class="token punctuation">.</span><span class="token function">contextify</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>context<span class="token punctuation">,</span> part<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> relativePath<span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">"!"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">/*
!!${relativeRequest}
relativeRequest../../node_modules/css-loader/dist/cjs.js!./index.css
relativeRequest是inline loader用法代表要处理的index.css资源, 使用css-loader处理
!!代表禁用所有配置的loader只使用inline loader。也就是外面我们style-loader和css-loader,它们被禁用了只是用我们指定的inline loader也就是css-loader
import style from "!!${relativeRequest}"
引入css-loader处理后的css文件
为什么需要css-loader处理css文件不是我们直接读取css文件使用呢
因为可能存在@import导入css语法这些语法就要通过css-loader解析才能变成一个css文件否则我们引入的css资源会缺少
const styleEl = document.createElement('style')
动态创建style标签
styleEl.innerHTML = style
将style标签内容设置为处理后的css代码
document.head.appendChild(styleEl)
添加到head中生效
*/</span>
<span class="token keyword">const</span> script <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">
import style from "!!</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>relativeRequest<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">"
const styleEl = document.createElement('style')
styleEl.innerHTML = style
document.head.appendChild(styleEl)
</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
<span class="token comment">// style-loader是第一个loader, 由于return导致熔断所以其他loader不执行了不管是normal还是pitch</span>
<span class="token keyword">return</span> script<span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
module<span class="token punctuation">.</span>exports <span class="token operator">=</span> styleLoader<span class="token punctuation">;</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br></div></div></template>

View File

@@ -0,0 +1,130 @@
export const data = {
"key": "v-2d7562d6",
"path": "/origin/plugin.html",
"title": "Plugin 原理",
"lang": "zh-CN",
"frontmatter": {},
"excerpt": "",
"headers": [
{
"level": 2,
"title": "Plugin 的作用",
"slug": "plugin-的作用",
"children": []
},
{
"level": 2,
"title": "Plugin 工作原理",
"slug": "plugin-工作原理",
"children": []
},
{
"level": 2,
"title": "Webpack 内部的钩子",
"slug": "webpack-内部的钩子",
"children": [
{
"level": 3,
"title": "什么是钩子",
"slug": "什么是钩子",
"children": []
},
{
"level": 3,
"title": "Tapable",
"slug": "tapable",
"children": []
}
]
},
{
"level": 2,
"title": "Plugin 构建对象",
"slug": "plugin-构建对象",
"children": [
{
"level": 3,
"title": "Compiler",
"slug": "compiler",
"children": []
},
{
"level": 3,
"title": "Compilation",
"slug": "compilation",
"children": []
},
{
"level": 3,
"title": "生命周期简图",
"slug": "生命周期简图",
"children": []
}
]
},
{
"level": 2,
"title": "开发一个插件",
"slug": "开发一个插件",
"children": [
{
"level": 3,
"title": "最简单的插件",
"slug": "最简单的插件",
"children": []
},
{
"level": 3,
"title": "注册 hook",
"slug": "注册-hook",
"children": []
},
{
"level": 3,
"title": "启动调试",
"slug": "启动调试",
"children": []
}
]
},
{
"level": 2,
"title": "BannerWebpackPlugin",
"slug": "bannerwebpackplugin",
"children": []
},
{
"level": 2,
"title": "CleanWebpackPlugin",
"slug": "cleanwebpackplugin",
"children": []
},
{
"level": 2,
"title": "AnalyzeWebpackPlugin",
"slug": "analyzewebpackplugin",
"children": []
},
{
"level": 2,
"title": "InlineChunkWebpackPlugin",
"slug": "inlinechunkwebpackplugin",
"children": []
}
],
"git": {},
"filePathRelative": "origin/plugin.md"
}
if (import.meta.webpackHot) {
import.meta.webpackHot.accept()
if (__VUE_HMR_RUNTIME__.updatePageData) {
__VUE_HMR_RUNTIME__.updatePageData(data)
}
}
if (import.meta.hot) {
import.meta.hot.accept(({ data }) => {
__VUE_HMR_RUNTIME__.updatePageData(data)
})
}

View File

@@ -0,0 +1,423 @@
<template><h1 id="plugin-原理" tabindex="-1"><a class="header-anchor" href="#plugin-原理" aria-hidden="true">#</a> Plugin 原理</h1>
<h2 id="plugin-的作用" tabindex="-1"><a class="header-anchor" href="#plugin-的作用" aria-hidden="true">#</a> Plugin 的作用</h2>
<p>通过插件我们可以扩展 webpack加入自定义的构建行为使 webpack 可以执行更广泛的任务拥有更强的构建能力</p>
<h2 id="plugin-工作原理" tabindex="-1"><a class="header-anchor" href="#plugin-工作原理" aria-hidden="true">#</a> Plugin 工作原理</h2>
<blockquote>
<p>webpack 就像一条生产线要经过一系列处理流程后才能将源文件转换成输出结果 这条生产线上的每个处理流程的职责都是单一的多个流程之间有存在依赖关系只有完成当前处理后才能交给下一个流程去处理
插件就像是一个插入到生产线中的一个功能在特定的时机对生产线上的资源做处理webpack 通过 Tapable 来组织这条复杂的生产线 webpack 在运行过程中会广播事件插件只需要监听它所关心的事件就能加入到这条生产线中去改变生产线的运作
webpack 的事件流机制保证了插件的有序性使得整个系统扩展性很好
深入浅出 Webpack</p>
</blockquote>
<p>站在代码逻辑的角度就是webpack 在编译代码过程中会触发一系列 <code>Tapable</code> 钩子事件插件所做的就是找到相应的钩子往上面挂上自己的任务也就是注册事件这样 webpack 构建的时候插件注册的事件就会随着钩子的触发而执行了</p>
<h2 id="webpack-内部的钩子" tabindex="-1"><a class="header-anchor" href="#webpack-内部的钩子" aria-hidden="true">#</a> Webpack 内部的钩子</h2>
<h3 id="什么是钩子" tabindex="-1"><a class="header-anchor" href="#什么是钩子" aria-hidden="true">#</a> 什么是钩子</h3>
<p>钩子的本质就是事件为了方便我们直接介入和控制编译过程webpack 把编译过程中触发的各类关键事件封装成事件接口暴露了出来这些接口被很形象地称做<code>hooks</code>钩子开发插件离不开这些钩子</p>
<h3 id="tapable" tabindex="-1"><a class="header-anchor" href="#tapable" aria-hidden="true">#</a> Tapable</h3>
<p><code>Tapable</code> webpack 提供了统一的插件接口钩子类型定义它是 webpack 的核心功能库webpack 中目前有十种 <code>hooks</code> <code>Tapable</code> 源码中可以看到他们是</p>
<div class="language-javascript ext-js line-numbers-mode"><pre v-pre class="language-javascript"><code><span class="token comment">// https://github.com/webpack/tapable/blob/master/lib/index.js</span>
exports<span class="token punctuation">.</span>SyncHook <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"./SyncHook"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
exports<span class="token punctuation">.</span>SyncBailHook <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"./SyncBailHook"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
exports<span class="token punctuation">.</span>SyncWaterfallHook <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"./SyncWaterfallHook"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
exports<span class="token punctuation">.</span>SyncLoopHook <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"./SyncLoopHook"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
exports<span class="token punctuation">.</span>AsyncParallelHook <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"./AsyncParallelHook"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
exports<span class="token punctuation">.</span>AsyncParallelBailHook <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"./AsyncParallelBailHook"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
exports<span class="token punctuation">.</span>AsyncSeriesHook <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"./AsyncSeriesHook"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
exports<span class="token punctuation">.</span>AsyncSeriesBailHook <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"./AsyncSeriesBailHook"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
exports<span class="token punctuation">.</span>AsyncSeriesLoopHook <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"./AsyncSeriesLoopHook"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
exports<span class="token punctuation">.</span>AsyncSeriesWaterfallHook <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"./AsyncSeriesWaterfallHook"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
exports<span class="token punctuation">.</span>HookMap <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"./HookMap"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
exports<span class="token punctuation">.</span>MultiHook <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"./MultiHook"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br></div></div><p><code>Tapable</code> 还统一暴露了三个方法给插件用于注入不同类型的自定义构建行为</p>
<ul>
<li><code>tap</code>可以注册同步钩子和异步钩子</li>
<li><code>tapAsync</code>回调方式注册异步钩子</li>
<li><code>tapPromise</code>Promise 方式注册异步钩子</li>
</ul>
<h2 id="plugin-构建对象" tabindex="-1"><a class="header-anchor" href="#plugin-构建对象" aria-hidden="true">#</a> Plugin 构建对象</h2>
<h3 id="compiler" tabindex="-1"><a class="header-anchor" href="#compiler" aria-hidden="true">#</a> Compiler</h3>
<p>compiler 对象中保存着完整的 Webpack 环境配置每次启动 webpack 构建时它都是一个独一无二仅仅会创建一次的对象</p>
<p>这个对象会在首次启动 Webpack 时创建我们可以通过 compiler 对象上访问到 Webapck 的主环境配置比如 loader plugin 等等配置信息</p>
<p>它有以下主要属性</p>
<ul>
<li><code>compiler.options</code> 可以访问本次启动 webpack 时候所有的配置文件包括但不限于 loaders entry output plugin 等等完整配置信息</li>
<li><code>compiler.inputFileSystem</code> <code>compiler.outputFileSystem</code> 可以进行文件操作相当于 Nodejs fs</li>
<li><code>compiler.hooks</code> 可以注册 tapable 的不同种类 Hook从而可以在 compiler 生命周期中植入不同的逻辑</li>
</ul>
<blockquote>
<p><a href="https://webpack.docschina.org/api/compiler-hooks/" target="_blank" rel="noopener noreferrer">compiler hooks 文档<ExternalLinkIcon/></a></p>
</blockquote>
<h3 id="compilation" tabindex="-1"><a class="header-anchor" href="#compilation" aria-hidden="true">#</a> Compilation</h3>
<p>compilation 对象代表一次资源的构建compilation 实例能够访问所有的模块和它们的依赖</p>
<p>一个 compilation 对象会对构建依赖图中所有模块进行编译 在编译阶段模块会被加载(load)封存(seal)优化(optimize) 分块(chunk)哈希(hash)和重新创建(restore)</p>
<p>它有以下主要属性</p>
<ul>
<li><code>compilation.modules</code> 可以访问所有模块打包的每一个文件都是一个模块</li>
<li><code>compilation.chunks</code> chunk 即是多个 modules 组成而来的一个代码块入口文件引入的资源组成一个 chunk通过代码分割的模块又是另外的 chunk</li>
<li><code>compilation.assets</code> 可以访问本次打包生成所有文件的结果</li>
<li><code>compilation.hooks</code> 可以注册 tapable 的不同种类 Hook用于在 compilation 编译模块阶段进行逻辑添加以及修改</li>
</ul>
<blockquote>
<p><a href="https://webpack.docschina.org/api/compilation-hooks/" target="_blank" rel="noopener noreferrer">compilation hooks 文档<ExternalLinkIcon/></a></p>
</blockquote>
<h3 id="生命周期简图" tabindex="-1"><a class="header-anchor" href="#生命周期简图" aria-hidden="true">#</a> 生命周期简图</h3>
<p><img src="/imgs/source/plugin.jpg" alt="Webpack 插件生命周期"></p>
<h2 id="开发一个插件" tabindex="-1"><a class="header-anchor" href="#开发一个插件" aria-hidden="true">#</a> 开发一个插件</h2>
<h3 id="最简单的插件" tabindex="-1"><a class="header-anchor" href="#最简单的插件" aria-hidden="true">#</a> 最简单的插件</h3>
<ul>
<li>plugins/test-plugin.js</li>
</ul>
<div class="language-javascript ext-js line-numbers-mode"><pre v-pre class="language-javascript"><code><span class="token keyword">class</span> <span class="token class-name">TestPlugin</span> <span class="token punctuation">{</span>
<span class="token function">constructor</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"TestPlugin constructor()"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// 1. webpack读取配置时new TestPlugin() ,会执行插件 constructor 方法</span>
<span class="token comment">// 2. webpack创建 compiler 对象</span>
<span class="token comment">// 3. 遍历所有插件,调用插件的 apply 方法</span>
<span class="token function">apply</span><span class="token punctuation">(</span><span class="token parameter">compiler</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"TestPlugin apply()"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
module<span class="token punctuation">.</span>exports <span class="token operator">=</span> TestPlugin<span class="token punctuation">;</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br></div></div><h3 id="注册-hook" tabindex="-1"><a class="header-anchor" href="#注册-hook" aria-hidden="true">#</a> 注册 hook</h3>
<div class="language-javascript ext-js line-numbers-mode"><pre v-pre class="language-javascript"><code><span class="token keyword">class</span> <span class="token class-name">TestPlugin</span> <span class="token punctuation">{</span>
<span class="token function">constructor</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"TestPlugin constructor()"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// 1. webpack读取配置时new TestPlugin() ,会执行插件 constructor 方法</span>
<span class="token comment">// 2. webpack创建 compiler 对象</span>
<span class="token comment">// 3. 遍历所有插件,调用插件的 apply 方法</span>
<span class="token function">apply</span><span class="token punctuation">(</span><span class="token parameter">compiler</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"TestPlugin apply()"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 从文档可知, compile hook 是 SyncHook, 也就是同步钩子, 只能用tap注册</span>
compiler<span class="token punctuation">.</span>hooks<span class="token punctuation">.</span>compile<span class="token punctuation">.</span><span class="token function">tap</span><span class="token punctuation">(</span><span class="token string">"TestPlugin"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">compilationParams</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"compiler.compile()"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 从文档可知, make 是 AsyncParallelHook, 也就是异步并行钩子, 特点就是异步任务同时执行</span>
<span class="token comment">// 可以使用 tap、tapAsync、tapPromise 注册。</span>
<span class="token comment">// 如果使用tap注册的话进行异步操作是不会等待异步操作执行完成的。</span>
compiler<span class="token punctuation">.</span>hooks<span class="token punctuation">.</span>make<span class="token punctuation">.</span><span class="token function">tap</span><span class="token punctuation">(</span><span class="token string">"TestPlugin"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">compilation</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token function">setTimeout</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"compiler.make() 111"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token number">2000</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 使用tapAsync、tapPromise注册进行异步操作会等异步操作做完再继续往下执行</span>
compiler<span class="token punctuation">.</span>hooks<span class="token punctuation">.</span>make<span class="token punctuation">.</span><span class="token function">tapAsync</span><span class="token punctuation">(</span><span class="token string">"TestPlugin"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">compilation<span class="token punctuation">,</span> callback</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token function">setTimeout</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"compiler.make() 222"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 必须调用</span>
<span class="token function">callback</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
compiler<span class="token punctuation">.</span>hooks<span class="token punctuation">.</span>make<span class="token punctuation">.</span><span class="token function">tapPromise</span><span class="token punctuation">(</span><span class="token string">"TestPlugin"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">compilation</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"compiler.make() 333"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 必须返回promise</span>
<span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">Promise</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">resolve</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token function">resolve</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 从文档可知, emit 是 AsyncSeriesHook, 也就是异步串行钩子,特点就是异步任务顺序执行</span>
compiler<span class="token punctuation">.</span>hooks<span class="token punctuation">.</span>emit<span class="token punctuation">.</span><span class="token function">tapAsync</span><span class="token punctuation">(</span><span class="token string">"TestPlugin"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">compilation<span class="token punctuation">,</span> callback</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token function">setTimeout</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"compiler.emit() 111"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">callback</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token number">3000</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
compiler<span class="token punctuation">.</span>hooks<span class="token punctuation">.</span>emit<span class="token punctuation">.</span><span class="token function">tapAsync</span><span class="token punctuation">(</span><span class="token string">"TestPlugin"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">compilation<span class="token punctuation">,</span> callback</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token function">setTimeout</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"compiler.emit() 222"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">callback</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token number">2000</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
compiler<span class="token punctuation">.</span>hooks<span class="token punctuation">.</span>emit<span class="token punctuation">.</span><span class="token function">tapAsync</span><span class="token punctuation">(</span><span class="token string">"TestPlugin"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">compilation<span class="token punctuation">,</span> callback</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token function">setTimeout</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"compiler.emit() 333"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">callback</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
module<span class="token punctuation">.</span>exports <span class="token operator">=</span> TestPlugin<span class="token punctuation">;</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br><span class="line-number">62</span><br><span class="line-number">63</span><br><span class="line-number">64</span><br><span class="line-number">65</span><br><span class="line-number">66</span><br></div></div><h3 id="启动调试" tabindex="-1"><a class="header-anchor" href="#启动调试" aria-hidden="true">#</a> 启动调试</h3>
<p>通过调试查看 <code>compiler</code> <code>compilation</code> 对象数据情况</p>
<ol>
<li>package.json 配置指令</li>
</ol>
<div class="language-json ext-json line-numbers-mode"><pre v-pre class="language-json"><code><span class="token punctuation">{</span>
<span class="token property">"name"</span><span class="token operator">:</span> <span class="token string">"source"</span><span class="token punctuation">,</span>
<span class="token property">"version"</span><span class="token operator">:</span> <span class="token string">"1.0.0"</span><span class="token punctuation">,</span>
<span class="token property">"scripts"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
<span class="token property">"debug"</span><span class="token operator">:</span> <span class="token string">"node --inspect-brk ./node_modules/webpack-cli/bin/cli.js"</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token property">"keywords"</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token property">"author"</span><span class="token operator">:</span> <span class="token string">"xiongjian"</span><span class="token punctuation">,</span>
<span class="token property">"license"</span><span class="token operator">:</span> <span class="token string">"ISC"</span><span class="token punctuation">,</span>
<span class="token property">"devDependencies"</span><span class="token operator">:</span> <span class="token punctuation">{</span>
<span class="token property">"@babel/core"</span><span class="token operator">:</span> <span class="token string">"^7.17.10"</span><span class="token punctuation">,</span>
<span class="token property">"@babel/preset-env"</span><span class="token operator">:</span> <span class="token string">"^7.17.10"</span><span class="token punctuation">,</span>
<span class="token property">"css-loader"</span><span class="token operator">:</span> <span class="token string">"^6.7.1"</span><span class="token punctuation">,</span>
<span class="token property">"loader-utils"</span><span class="token operator">:</span> <span class="token string">"^3.2.0"</span><span class="token punctuation">,</span>
<span class="token property">"webpack"</span><span class="token operator">:</span> <span class="token string">"^5.72.0"</span><span class="token punctuation">,</span>
<span class="token property">"webpack-cli"</span><span class="token operator">:</span> <span class="token string">"^4.9.2"</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre><div class="highlight-lines"><br><br><br><br><div class="highlight-line">&nbsp;</div><br><br><br><br><br><br><br><br><br><br><br><br><br></div><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br></div></div><ol start="2">
<li>运行指令</li>
</ol>
<div class="language-text ext-text line-numbers-mode"><pre v-pre class="language-text"><code>npm run debug
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br></div></div><p>此时控制台输出以下内容</p>
<div class="language-text ext-text line-numbers-mode"><pre v-pre class="language-text"><code>PS C:\Users\86176\Desktop\source> npm run debug
> source@1.0.0 debug
> node --inspect-brk ./node_modules/webpack-cli/bin/cli.js
Debugger listening on ws://127.0.0.1:9229/629ea097-7b52-4011-93a7-02f83c75c797
For help, see: https://nodejs.org/en/docs/inspecto
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br></div></div><ol start="3">
<li>打开 Chrome 浏览器F12 打开浏览器调试控制台</li>
</ol>
<p>此时控制台会显示一个绿色的图标</p>
<p><img src="/imgs/source/debug.png" alt="调试控制台"></p>
<ol start="4">
<li>
<p>点击绿色的图标进入调试模式</p>
</li>
<li>
<p>在需要调试代码处用 <code>debugger</code> 打断点代码就会停止运行从而调试查看数据情况</p>
</li>
</ol>
<h2 id="bannerwebpackplugin" tabindex="-1"><a class="header-anchor" href="#bannerwebpackplugin" aria-hidden="true">#</a> BannerWebpackPlugin</h2>
<ol>
<li>
<p>作用给打包输出文件添加注释</p>
</li>
<li>
<p>开发思路:</p>
</li>
</ol>
<ul>
<li>需要打包输出前添加注释需要使用 <code>compiler.hooks.emit</code> 钩子, 它是打包输出前触发</li>
<li>如何获取打包输出的资源<code>compilation.assets</code> 可以获取所有即将输出的资源文件</li>
</ul>
<ol start="3">
<li>实现</li>
</ol>
<div class="language-javascript ext-js line-numbers-mode"><pre v-pre class="language-javascript"><code><span class="token comment">// plugins/banner-webpack-plugin.js</span>
<span class="token keyword">class</span> <span class="token class-name">BannerWebpackPlugin</span> <span class="token punctuation">{</span>
<span class="token function">constructor</span><span class="token punctuation">(</span><span class="token parameter">options <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>options <span class="token operator">=</span> options<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token function">apply</span><span class="token punctuation">(</span><span class="token parameter">compiler</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// 需要处理文件</span>
<span class="token keyword">const</span> extensions <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token string">"js"</span><span class="token punctuation">,</span> <span class="token string">"css"</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token comment">// emit是异步串行钩子</span>
compiler<span class="token punctuation">.</span>hooks<span class="token punctuation">.</span>emit<span class="token punctuation">.</span><span class="token function">tapAsync</span><span class="token punctuation">(</span><span class="token string">"BannerWebpackPlugin"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">compilation<span class="token punctuation">,</span> callback</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token comment">// compilation.assets包含所有即将输出的资源</span>
<span class="token comment">// 通过过滤只保留需要处理的文件</span>
<span class="token keyword">const</span> assetPaths <span class="token operator">=</span> Object<span class="token punctuation">.</span><span class="token function">keys</span><span class="token punctuation">(</span>compilation<span class="token punctuation">.</span>assets<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">filter</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">path</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> splitted <span class="token operator">=</span> path<span class="token punctuation">.</span><span class="token function">split</span><span class="token punctuation">(</span><span class="token string">"."</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> extensions<span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span>splitted<span class="token punctuation">[</span>splitted<span class="token punctuation">.</span>length <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
assetPaths<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">assetPath</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> asset <span class="token operator">=</span> compilation<span class="token punctuation">.</span>assets<span class="token punctuation">[</span>assetPath<span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> source <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">/*
* Author: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token keyword">this</span><span class="token punctuation">.</span>options<span class="token punctuation">.</span>author<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">
*/\n</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>asset<span class="token punctuation">.</span><span class="token function">source</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
<span class="token comment">// 覆盖资源</span>
compilation<span class="token punctuation">.</span>assets<span class="token punctuation">[</span>assetPath<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">{</span>
<span class="token comment">// 资源内容</span>
<span class="token function">source</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> source<span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token comment">// 资源大小</span>
<span class="token function">size</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> source<span class="token punctuation">.</span>length<span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">callback</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
module<span class="token punctuation">.</span>exports <span class="token operator">=</span> BannerWebpackPlugin<span class="token punctuation">;</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br></div></div><h2 id="cleanwebpackplugin" tabindex="-1"><a class="header-anchor" href="#cleanwebpackplugin" aria-hidden="true">#</a> CleanWebpackPlugin</h2>
<ol>
<li>
<p>作用 webpack 打包输出前将上次打包内容清空</p>
</li>
<li>
<p>开发思路</p>
</li>
</ol>
<ul>
<li>如何在打包输出前执行需要使用 <code>compiler.hooks.emit</code> 钩子, 它是打包输出前触发</li>
<li>如何清空上次打包内容
<ul>
<li>获取打包输出目录通过 compiler 对象</li>
<li>通过文件操作清空内容通过 <code>compiler.outputFileSystem</code> 操作文件</li>
</ul>
</li>
</ul>
<ol start="3">
<li>实现</li>
</ol>
<div class="language-javascript ext-js line-numbers-mode"><pre v-pre class="language-javascript"><code><span class="token comment">// plugins/clean-webpack-plugin.js</span>
<span class="token keyword">class</span> <span class="token class-name">CleanWebpackPlugin</span> <span class="token punctuation">{</span>
<span class="token function">apply</span><span class="token punctuation">(</span><span class="token parameter">compiler</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// 获取操作文件的对象</span>
<span class="token keyword">const</span> fs <span class="token operator">=</span> compiler<span class="token punctuation">.</span>outputFileSystem<span class="token punctuation">;</span>
<span class="token comment">// emit是异步串行钩子</span>
compiler<span class="token punctuation">.</span>hooks<span class="token punctuation">.</span>emit<span class="token punctuation">.</span><span class="token function">tapAsync</span><span class="token punctuation">(</span><span class="token string">"CleanWebpackPlugin"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">compilation<span class="token punctuation">,</span> callback</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token comment">// 获取输出文件目录</span>
<span class="token keyword">const</span> outputPath <span class="token operator">=</span> compiler<span class="token punctuation">.</span>options<span class="token punctuation">.</span>output<span class="token punctuation">.</span>path<span class="token punctuation">;</span>
<span class="token comment">// 删除目录所有文件</span>
<span class="token keyword">const</span> err <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">removeFiles</span><span class="token punctuation">(</span>fs<span class="token punctuation">,</span> outputPath<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 执行成功err为undefined执行失败err就是错误原因</span>
<span class="token function">callback</span><span class="token punctuation">(</span>err<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token function">removeFiles</span><span class="token punctuation">(</span><span class="token parameter">fs<span class="token punctuation">,</span> path</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">try</span> <span class="token punctuation">{</span>
<span class="token comment">// 读取当前目录下所有文件</span>
<span class="token keyword">const</span> files <span class="token operator">=</span> fs<span class="token punctuation">.</span><span class="token function">readdirSync</span><span class="token punctuation">(</span>path<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 遍历文件,删除</span>
files<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">file</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token comment">// 获取文件完整路径</span>
<span class="token keyword">const</span> filePath <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>path<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">/</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>file<span class="token interpolation-punctuation punctuation">}</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
<span class="token comment">// 分析文件</span>
<span class="token keyword">const</span> fileStat <span class="token operator">=</span> fs<span class="token punctuation">.</span><span class="token function">statSync</span><span class="token punctuation">(</span>filePath<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 判断是否是文件夹</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>fileStat<span class="token punctuation">.</span><span class="token function">isDirectory</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// 是文件夹需要递归遍历删除下面所有文件</span>
<span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">removeFiles</span><span class="token punctuation">(</span>fs<span class="token punctuation">,</span> filePath<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
<span class="token comment">// 不是文件夹就是文件,直接删除</span>
fs<span class="token punctuation">.</span><span class="token function">unlinkSync</span><span class="token punctuation">(</span>filePath<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 最后删除当前目录</span>
fs<span class="token punctuation">.</span><span class="token function">rmdirSync</span><span class="token punctuation">(</span>path<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span>e<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// 将产生的错误返回出去</span>
<span class="token keyword">return</span> e<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
module<span class="token punctuation">.</span>exports <span class="token operator">=</span> CleanWebpackPlugin<span class="token punctuation">;</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br></div></div><h2 id="analyzewebpackplugin" tabindex="-1"><a class="header-anchor" href="#analyzewebpackplugin" aria-hidden="true">#</a> AnalyzeWebpackPlugin</h2>
<ol>
<li>作用分析 webpack 打包资源大小并输出分析文件</li>
<li>开发思路:</li>
</ol>
<ul>
<li>在哪做? <code>compiler.hooks.emit</code>, 它是在打包输出前触发我们需要分析资源大小同时添加上分析后的 md 文件</li>
</ul>
<ol start="3">
<li>实现</li>
</ol>
<div class="language-javascript ext-js line-numbers-mode"><pre v-pre class="language-javascript"><code><span class="token comment">// plugins/analyze-webpack-plugin.js</span>
<span class="token keyword">class</span> <span class="token class-name">AnalyzeWebpackPlugin</span> <span class="token punctuation">{</span>
<span class="token function">apply</span><span class="token punctuation">(</span><span class="token parameter">compiler</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// emit是异步串行钩子</span>
compiler<span class="token punctuation">.</span>hooks<span class="token punctuation">.</span>emit<span class="token punctuation">.</span><span class="token function">tap</span><span class="token punctuation">(</span><span class="token string">"AnalyzeWebpackPlugin"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">compilation</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token comment">// Object.entries将对象变成二维数组。二维数组中第一项值是key第二项值是value</span>
<span class="token keyword">const</span> assets <span class="token operator">=</span> Object<span class="token punctuation">.</span><span class="token function">entries</span><span class="token punctuation">(</span>compilation<span class="token punctuation">.</span>assets<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> source <span class="token operator">=</span> <span class="token string">"# 分析打包资源大小 \n| 名称 | 大小 |\n| --- | --- |"</span><span class="token punctuation">;</span>
assets<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">[</span>filename<span class="token punctuation">,</span> file<span class="token punctuation">]</span></span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
source <span class="token operator">+=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">\n| </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>filename<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> | </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>file<span class="token punctuation">.</span><span class="token function">size</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string"> |</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 添加资源</span>
compilation<span class="token punctuation">.</span>assets<span class="token punctuation">[</span><span class="token string">"analyze.md"</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">{</span>
<span class="token function">source</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> source<span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token function">size</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> source<span class="token punctuation">.</span>length<span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
module<span class="token punctuation">.</span>exports <span class="token operator">=</span> AnalyzeWebpackPlugin<span class="token punctuation">;</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br></div></div><h2 id="inlinechunkwebpackplugin" tabindex="-1"><a class="header-anchor" href="#inlinechunkwebpackplugin" aria-hidden="true">#</a> InlineChunkWebpackPlugin</h2>
<ol>
<li>作用webpack 打包生成的 runtime 文件太小了额外发送请求性能不好所以需要将其内联到 js 从而减少请求数量</li>
<li>开发思路:</li>
</ol>
<ul>
<li>我们需要借助 <code>html-webpack-plugin</code> 来实现
<ul>
<li> <code>html-webpack-plugin</code> 输出 index.html 前将内联 runtime 注入进去</li>
<li>删除多余的 runtime 文件</li>
</ul>
</li>
<li>如何操作 <code>html-webpack-plugin</code><a href="https://github.com/jantimon/html-webpack-plugin/#afteremit-hook" target="_blank" rel="noopener noreferrer">官方文档<ExternalLinkIcon/></a></li>
</ul>
<ol start="3">
<li>实现</li>
</ol>
<div class="language-javascript ext-js line-numbers-mode"><pre v-pre class="language-javascript"><code><span class="token comment">// plugins/inline-chunk-webpack-plugin.js</span>
<span class="token keyword">const</span> HtmlWebpackPlugin <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">"safe-require"</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token string">"html-webpack-plugin"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">class</span> <span class="token class-name">InlineChunkWebpackPlugin</span> <span class="token punctuation">{</span>
<span class="token function">constructor</span><span class="token punctuation">(</span><span class="token parameter">tests</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>tests <span class="token operator">=</span> tests<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token function">apply</span><span class="token punctuation">(</span><span class="token parameter">compiler</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
compiler<span class="token punctuation">.</span>hooks<span class="token punctuation">.</span>compilation<span class="token punctuation">.</span><span class="token function">tap</span><span class="token punctuation">(</span><span class="token string">"InlineChunkWebpackPlugin"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">compilation</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> hooks <span class="token operator">=</span> HtmlWebpackPlugin<span class="token punctuation">.</span><span class="token function">getHooks</span><span class="token punctuation">(</span>compilation<span class="token punctuation">)</span><span class="token punctuation">;</span>
hooks<span class="token punctuation">.</span>alterAssetTagGroups<span class="token punctuation">.</span><span class="token function">tap</span><span class="token punctuation">(</span><span class="token string">"InlineChunkWebpackPlugin"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">assets</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
assets<span class="token punctuation">.</span>headTags <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">getInlineTag</span><span class="token punctuation">(</span>assets<span class="token punctuation">.</span>headTags<span class="token punctuation">,</span> compilation<span class="token punctuation">.</span>assets<span class="token punctuation">)</span><span class="token punctuation">;</span>
assets<span class="token punctuation">.</span>bodyTags <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">getInlineTag</span><span class="token punctuation">(</span>assets<span class="token punctuation">.</span>bodyTags<span class="token punctuation">,</span> compilation<span class="token punctuation">.</span>assets<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
hooks<span class="token punctuation">.</span>afterEmit<span class="token punctuation">.</span><span class="token function">tap</span><span class="token punctuation">(</span><span class="token string">"InlineChunkHtmlPlugin"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
Object<span class="token punctuation">.</span><span class="token function">keys</span><span class="token punctuation">(</span>compilation<span class="token punctuation">.</span>assets<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">assetName</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>tests<span class="token punctuation">.</span><span class="token function">some</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">test</span><span class="token punctuation">)</span> <span class="token operator">=></span> assetName<span class="token punctuation">.</span><span class="token function">match</span><span class="token punctuation">(</span>test<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">delete</span> compilation<span class="token punctuation">.</span>assets<span class="token punctuation">[</span>assetName<span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token function">getInlineTag</span><span class="token punctuation">(</span><span class="token parameter">tags<span class="token punctuation">,</span> assets</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> tags<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">tag</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>tag<span class="token punctuation">.</span>tagName <span class="token operator">!==</span> <span class="token string">"script"</span><span class="token punctuation">)</span> <span class="token keyword">return</span> tag<span class="token punctuation">;</span>
<span class="token keyword">const</span> scriptName <span class="token operator">=</span> tag<span class="token punctuation">.</span>attributes<span class="token punctuation">.</span>src<span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token keyword">this</span><span class="token punctuation">.</span>tests<span class="token punctuation">.</span><span class="token function">some</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">test</span><span class="token punctuation">)</span> <span class="token operator">=></span> scriptName<span class="token punctuation">.</span><span class="token function">match</span><span class="token punctuation">(</span>test<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token keyword">return</span> tag<span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token punctuation">{</span> <span class="token literal-property property">tagName</span><span class="token operator">:</span> <span class="token string">"script"</span><span class="token punctuation">,</span> <span class="token literal-property property">innerHTML</span><span class="token operator">:</span> assets<span class="token punctuation">[</span>scriptName<span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">source</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token literal-property property">closeTag</span><span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
module<span class="token punctuation">.</span>exports <span class="token operator">=</span> InlineChunkWebpackPlugin<span class="token punctuation">;</span>
</code></pre><div class="line-numbers" aria-hidden="true"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br></div></div></template>

View File

@@ -0,0 +1,24 @@
export const data = {
"key": "v-860cdcba",
"path": "/origin/summary.html",
"title": "总结",
"lang": "zh-CN",
"frontmatter": {},
"excerpt": "",
"headers": [],
"git": {},
"filePathRelative": "origin/summary.md"
}
if (import.meta.webpackHot) {
import.meta.webpackHot.accept()
if (__VUE_HMR_RUNTIME__.updatePageData) {
__VUE_HMR_RUNTIME__.updatePageData(data)
}
}
if (import.meta.hot) {
import.meta.hot.accept(({ data }) => {
__VUE_HMR_RUNTIME__.updatePageData(data)
})
}

View File

@@ -0,0 +1,4 @@
<template><h1 id="总结" tabindex="-1"><a class="header-anchor" href="#总结" aria-hidden="true">#</a> 总结</h1>
<p>本章节我们学习了 webpack 中的 loader plugin 用法包括是什么怎么使用如何自定义等</p>
<p>它能够帮助大家提升对 loader plugin 的认识同时学习到了原理将来大家也能够在社区中做出贡献</p>
</template>