fix img & index.html & .md.html

This commit is contained in:
by931
2022-08-14 03:40:33 +08:00
parent 85b6063789
commit 08120ee33c
3375 changed files with 151526 additions and 1217663 deletions

View File

@@ -12,9 +12,7 @@
<!-- theme css & js -->
<meta name="generator" content="Hexo 4.2.0">
</head>
<body>
<div class="book-container">
<div class="book-sidebar">
<div class="book-brand">
@@ -27,176 +25,98 @@
<ul class="uncollapsible">
<li><a href="/" class="current-tab">首页</a></li>
</ul>
<ul class="uncollapsible">
<li><a href="../">上一级</a></li>
</ul>
<ul class="uncollapsible">
<li>
<a href="/专栏/前端工程化精讲-完/00 开篇词 建立上帝视角,全面系统掌握前端效率工程化.md.html">00 开篇词 建立上帝视角,全面系统掌握前端效率工程化.md.html</a>
<a href="/专栏/前端工程化精讲-完/00 开篇词 建立上帝视角,全面系统掌握前端效率工程化.md.html">00 开篇词 建立上帝视角,全面系统掌握前端效率工程化</a>
</li>
<li>
<a href="/专栏/前端工程化精讲-完/01 项目基石:前端脚手架工具探秘.md.html">01 项目基石:前端脚手架工具探秘.md.html</a>
<a href="/专栏/前端工程化精讲-完/01 项目基石:前端脚手架工具探秘.md.html">01 项目基石:前端脚手架工具探秘</a>
</li>
<li>
<a class="current-tab" href="/专栏/前端工程化精讲-完/02 界面调试:热更新技术如何开着飞机修引擎?.md.html">02 界面调试:热更新技术如何开着飞机修引擎?.md.html</a>
<a class="current-tab" href="/专栏/前端工程化精讲-完/02 界面调试:热更新技术如何开着飞机修引擎?.md.html">02 界面调试:热更新技术如何开着飞机修引擎?</a>
</li>
<li>
<a href="/专栏/前端工程化精讲-完/03 构建提速:如何正确使用 SourceMap.md.html">03 构建提速:如何正确使用 SourceMap.md.html</a>
<a href="/专栏/前端工程化精讲-完/03 构建提速:如何正确使用 SourceMap.md.html">03 构建提速:如何正确使用 SourceMap</a>
</li>
<li>
<a href="/专栏/前端工程化精讲-完/04 接口调试Mock 工具如何快速进行接口调试?.md.html">04 接口调试Mock 工具如何快速进行接口调试?.md.html</a>
<a href="/专栏/前端工程化精讲-完/04 接口调试Mock 工具如何快速进行接口调试?.md.html">04 接口调试Mock 工具如何快速进行接口调试?</a>
</li>
<li>
<a href="/专栏/前端工程化精讲-完/05 编码效率:如何提高编写代码的效率?.md.html">05 编码效率:如何提高编写代码的效率?.md.html</a>
<a href="/专栏/前端工程化精讲-完/05 编码效率:如何提高编写代码的效率?.md.html">05 编码效率:如何提高编写代码的效率?</a>
</li>
<li>
<a href="/专栏/前端工程化精讲-完/06 团队工具:如何利用云开发提升团队开发效率?.md.html">06 团队工具:如何利用云开发提升团队开发效率?.md.html</a>
<a href="/专栏/前端工程化精讲-完/06 团队工具:如何利用云开发提升团队开发效率?.md.html">06 团队工具:如何利用云开发提升团队开发效率?</a>
</li>
<li>
<a href="/专栏/前端工程化精讲-完/07 低代码工具:如何用更少的代码实现更灵活的需求.md.html">07 低代码工具:如何用更少的代码实现更灵活的需求.md.html</a>
<a href="/专栏/前端工程化精讲-完/07 低代码工具:如何用更少的代码实现更灵活的需求.md.html">07 低代码工具:如何用更少的代码实现更灵活的需求</a>
</li>
<li>
<a href="/专栏/前端工程化精讲-完/08 无代码工具:如何做到不写代码就能高效交付?.md.html">08 无代码工具:如何做到不写代码就能高效交付?.md.html</a>
<a href="/专栏/前端工程化精讲-完/08 无代码工具:如何做到不写代码就能高效交付?.md.html">08 无代码工具:如何做到不写代码就能高效交付?</a>
</li>
<li>
<a href="/专栏/前端工程化精讲-完/09 构建总览:前端构建工具的演进.md.html">09 构建总览:前端构建工具的演进.md.html</a>
<a href="/专栏/前端工程化精讲-完/09 构建总览:前端构建工具的演进.md.html">09 构建总览:前端构建工具的演进</a>
</li>
<li>
<a href="/专栏/前端工程化精讲-完/10 流程分解Webpack 的完整构建流程.md.html">10 流程分解Webpack 的完整构建流程.md.html</a>
<a href="/专栏/前端工程化精讲-完/10 流程分解Webpack 的完整构建流程.md.html">10 流程分解Webpack 的完整构建流程</a>
</li>
<li>
<a href="/专栏/前端工程化精讲-完/11 编译提效:如何为 Webpack 编译阶段提速?.md.html">11 编译提效:如何为 Webpack 编译阶段提速?.md.html</a>
<a href="/专栏/前端工程化精讲-完/11 编译提效:如何为 Webpack 编译阶段提速?.md.html">11 编译提效:如何为 Webpack 编译阶段提速?</a>
</li>
<li>
<a href="/专栏/前端工程化精讲-完/12 打包提效:如何为 Webpack 打包阶段提速?.md.html">12 打包提效:如何为 Webpack 打包阶段提速?.md.html</a>
<a href="/专栏/前端工程化精讲-完/12 打包提效:如何为 Webpack 打包阶段提速?.md.html">12 打包提效:如何为 Webpack 打包阶段提速?</a>
</li>
<li>
<a href="/专栏/前端工程化精讲-完/13 缓存优化:那些基于缓存的优化方案.md.html">13 缓存优化:那些基于缓存的优化方案.md.html</a>
<a href="/专栏/前端工程化精讲-完/13 缓存优化:那些基于缓存的优化方案.md.html">13 缓存优化:那些基于缓存的优化方案</a>
</li>
<li>
<a href="/专栏/前端工程化精讲-完/14 增量构建Webpack 中的增量构建.md.html">14 增量构建Webpack 中的增量构建.md.html</a>
<a href="/专栏/前端工程化精讲-完/14 增量构建Webpack 中的增量构建.md.html">14 增量构建Webpack 中的增量构建</a>
</li>
<li>
<a href="/专栏/前端工程化精讲-完/15 版本特性Webpack 5 中的优化细节.md.html">15 版本特性Webpack 5 中的优化细节.md.html</a>
<a href="/专栏/前端工程化精讲-完/15 版本特性Webpack 5 中的优化细节.md.html">15 版本特性Webpack 5 中的优化细节</a>
</li>
<li>
<a href="/专栏/前端工程化精讲-完/16 无包构建:盘点那些 No-bundle 的构建方案.md.html">16 无包构建:盘点那些 No-bundle 的构建方案.md.html</a>
<a href="/专栏/前端工程化精讲-完/16 无包构建:盘点那些 No-bundle 的构建方案.md.html">16 无包构建:盘点那些 No-bundle 的构建方案</a>
</li>
<li>
<a href="/专栏/前端工程化精讲-完/17 部署初探:为什么一般不在开发环境下部署代码?.md.html">17 部署初探:为什么一般不在开发环境下部署代码?.md.html</a>
<a href="/专栏/前端工程化精讲-完/17 部署初探:为什么一般不在开发环境下部署代码?.md.html">17 部署初探:为什么一般不在开发环境下部署代码?</a>
</li>
<li>
<a href="/专栏/前端工程化精讲-完/18 工具盘点:掌握那些流行的代码部署工具.md.html">18 工具盘点:掌握那些流行的代码部署工具.md.html</a>
<a href="/专栏/前端工程化精讲-完/18 工具盘点:掌握那些流行的代码部署工具.md.html">18 工具盘点:掌握那些流行的代码部署工具</a>
</li>
<li>
<a href="/专栏/前端工程化精讲-完/19 安装提效:部署流程中的依赖安装效率优化.md.html">19 安装提效:部署流程中的依赖安装效率优化.md.html</a>
<a href="/专栏/前端工程化精讲-完/19 安装提效:部署流程中的依赖安装效率优化.md.html">19 安装提效:部署流程中的依赖安装效率优化</a>
</li>
<li>
<a href="/专栏/前端工程化精讲-完/20 流程优化:部署流程中的构建流程策略优化.md.html">20 流程优化:部署流程中的构建流程策略优化.md.html</a>
<a href="/专栏/前端工程化精讲-完/20 流程优化:部署流程中的构建流程策略优化.md.html">20 流程优化:部署流程中的构建流程策略优化</a>
</li>
<li>
<a href="/专栏/前端工程化精讲-完/21 容器方案:从构建到部署,容器化方案的优势有哪些?.md.html">21 容器方案:从构建到部署,容器化方案的优势有哪些?.md.html</a>
<a href="/专栏/前端工程化精讲-完/21 容器方案:从构建到部署,容器化方案的优势有哪些?.md.html">21 容器方案:从构建到部署,容器化方案的优势有哪些?</a>
</li>
<li>
<a href="/专栏/前端工程化精讲-完/22 案例分析:搭建基本的前端高效部署系统.md.html">22 案例分析:搭建基本的前端高效部署系统.md.html</a>
<a href="/专栏/前端工程化精讲-完/22 案例分析:搭建基本的前端高效部署系统.md.html">22 案例分析:搭建基本的前端高效部署系统</a>
</li>
<li>
<a href="/专栏/前端工程化精讲-完/23 结束语 前端效率工程化的未来展望.md.html">23 结束语 前端效率工程化的未来展望.md.html</a>
<a href="/专栏/前端工程化精讲-完/23 结束语 前端效率工程化的未来展望.md.html">23 结束语 前端效率工程化的未来展望</a>
</li>
</ul>
</div>
</div>
<div class="sidebar-toggle" onclick="sidebar_toggle()" onmouseover="add_inner()" onmouseleave="remove_inner()">
<div class="sidebar-toggle-inner"></div>
</div>
<script>
function add_inner() {
let inner = document.querySelector('.sidebar-toggle-inner')
inner.classList.add('show')
}
function remove_inner() {
let inner = document.querySelector('.sidebar-toggle-inner')
inner.classList.remove('show')
}
function sidebar_toggle() {
let sidebar_toggle = document.querySelector('.sidebar-toggle')
let sidebar = document.querySelector('.book-sidebar')
@@ -211,8 +131,6 @@
content.classList.add('extend')
}
}
function open_sidebar() {
let sidebar = document.querySelector('.book-sidebar')
let overlay = document.querySelector('.off-canvas-overlay')
@@ -225,9 +143,7 @@ function hide_canvas() {
sidebar.classList.remove('show')
overlay.classList.remove('show')
}
</script>
<div class="off-canvas-content">
<div class="columns">
<div class="column col-12 col-lg-12">
@@ -259,54 +175,32 @@ function hide_canvas() {
<h4>一切依赖手动</h4>
<p>首先来看第一个最简单的配置,在入口 js 中我们简单地打印一个文本,然后在构建配置里只有最简单的 entry 和 mode 配置。</p>
<pre><code>src/index0.js
function render() {
div = document.createElement('div')
div.innerHTML = 'Hello World0';
document.body.appendChild(div)
}
render()
webpack.config.basic.js
module.exports = {
entry: './src/index0.js',
mode: 'development',
}
package.json
&quot;scripts&quot;: {
&quot;build:basic&quot;: &quot;webpack --config webpack.config.basic.js&quot;
function render() {
div = document.createElement('div')
div.innerHTML = 'Hello World0';
document.body.appendChild(div)
}
render()
webpack.config.basic.js
module.exports = {
entry: './src/index0.js',
mode: 'development',
}
package.json
&quot;scripts&quot;: {
&quot;build:basic&quot;: &quot;webpack --config webpack.config.basic.js&quot;
}
</code></pre>
<p>当我们执行 npm run build:basic 时webpack 将 entry 中的源文件 index0.js 打包为 dist/main.js并退出进程。流程很简单但是如果我们接下来改动了源文件的输出文本会发现由于构建配置中没有任何对应处理所以在保存后打包后的文件内容并没有更新。为了同步改动效果我们需要再次手动执行该命令。</p>
<h4>Watch 模式</h4>
<p>第二种配置是 watch 模式。为了摆脱每次修改文件后都需要手动执行脚本才能进行编译的问题webpack 中增加了 watch 模式,通过监控源码文件的变化来解决上面不能自动编译问题。我们可以在配置脚本中增加 watch:true如下</p>
<pre><code>webpack.config.watch.js
{...
watch: true
...}
package.json
&quot;scripts&quot;: {
&quot;build:watch&quot;: &quot;webpack --config webpack.config.watch.js&quot;
{...
watch: true
...}
package.json
&quot;scripts&quot;: {
&quot;build:watch&quot;: &quot;webpack --config webpack.config.watch.js&quot;
}
</code></pre>
<p>当我们执行 npm run build:watchwebpack 同样执行一次打包过程,但在打包结束后并未退出当前进程,而是继续<strong>监控源文件内容是否发生变化</strong>,当源文件发生变更后将再次执行该流程,直到用户主动退出(除了在配置文件中加入参数外,也可以在 webpack 命令中增加 --watch 来实现)。</p>
@@ -314,25 +208,15 @@ package.json
<h4>Live Reload</h4>
<p>第三种配置是 Live Reload。为了使每次代码变更后浏览器中的预览页面能自动显示最新效果而无须手动点击刷新我们需要<strong>一种通信机制来连接浏览器中的预览页面与本地监控代码变更的进程</strong>。在 webpack 中,我们可以使用官方提供的开发服务器来实现这一目的,配置如下:</p>
<pre><code>webpack.config.reload.js
{...
devServer: {
contentBase: './dist', //为./dist目录中的静态页面文件提供本地服务渲染
open: true //启动服务后自动打开浏览器网页
}
...}
package.json
&quot;scripts&quot;: {
&quot;dev:reload&quot;: &quot;webpack-dev-server --config webpack.config.reload.js&quot;
{...
devServer: {
contentBase: './dist', //为./dist目录中的静态页面文件提供本地服务渲染
open: true //启动服务后自动打开浏览器网页
}
...}
package.json
&quot;scripts&quot;: {
&quot;dev:reload&quot;: &quot;webpack-dev-server --config webpack.config.reload.js&quot;
}
</code></pre>
<p>当我们执行 npm run dev:reload从日志中可以看到本地服务 http://localhost:8080/ 已启动,然后我们在浏览器中输入网址 http://localhost:8080/index.html (也可以在 devServer 的配置中加入 open 和 openPage 来自动打开网页)并打开控制台网络面板,可以看到在加载完页面和页面中引用的 js 文件后,服务还加载了路径前缀名为 /sockjs-node 的 websocket 链接,如下图:</p>
@@ -342,55 +226,30 @@ package.json
<h4>Hot Module Replacement</h4>
<p>第四种配置就是我们常说的 HMRHot Module Replacement模块热替换了。为了解决页面刷新导致的状态丢失问题webpack 提出了模块热替换的概念。下面我们通过一个复杂一些的示例来了解热替换的配置与使用场景:</p>
<pre><code>src/index1.js
import './style.css'
...
src/style.css
div { color: red }
webpack.config.hmr.js
{...
entry: './src/index1.js',
...
devServer: {
...
hot: true
},
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
}
]
}
}
package.json
&quot;scripts&quot;: {
&quot;dev:hmr&quot;: &quot;webpack-dev-server --config webpack.config.hmr.js&quot;
import './style.css'
...
src/style.css
div { color: red }
webpack.config.hmr.js
{...
entry: './src/index1.js',
...
devServer: {
...
hot: true
},
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
}
]
}
}
package.json
&quot;scripts&quot;: {
&quot;dev:hmr&quot;: &quot;webpack-dev-server --config webpack.config.hmr.js&quot;
}
</code></pre>
<p>在上面的代码改动中,我们只是在源码部分新增导入了一个简单的 CSS 文件,用于演示热替换的效果。在配置文件中,首先我们在 devServer 配置中新增了 hot:true其次新增 module 的配置,使用 style-loader 和 css-loader 来解析导入的 CSS 文件。其中 css-loader 处理的是将导入的 CSS 文件转化为模块供后续 Loader 处理;而 style-loader 则是负责将 CSS 模块的内容在运行时添加到页面的 style 标签中。</p>
@@ -442,39 +301,22 @@ package.json
<h4>style-loader 中的热替换代码</h4>
<p>我们简化一下上述控制台中看到的 style-loader 处理后的模块代码,只看其热替换相关的部分。</p>
<pre><code>//为了清晰期间,我们将模块名称注释以及与热更新无关的逻辑省略,并将 css 内容模块路径赋值为变量 cssContentPath 以便多处引用,实际代码可从示例运行时中查看
var cssContentPath = &quot;./node_modules/css-loader/dist/cjs.js!./src/style.css&quot;
var api = __webpack_require__(&quot;./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js&quot;);
var content = __webpack_require__(cssContentPath);
...
var update = api(content, options);
...
module.hot.accept(
cssContentPath,
function(){
content = __webpack_require__(cssContentPath);
...
update(content);
}
)
module.hot.dispose(function() {
update();
var cssContentPath = &quot;./node_modules/css-loader/dist/cjs.js!./src/style.css&quot;
var api = __webpack_require__(&quot;./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js&quot;);
var content = __webpack_require__(cssContentPath);
...
var update = api(content, options);
...
module.hot.accept(
cssContentPath,
function(){
content = __webpack_require__(cssContentPath);
...
update(content);
}
)
module.hot.dispose(function() {
update();
});
</code></pre>
<p>从上面的代码中我们可以看到,在运行时调用 API 实现将样式注入新生成的 style 标签,并将返回函数传递给 update 变量。然后,在 module.hot.accept 方法的回调函数中执行 update(content),在 module.hot.dispose 中执行 update()。通过查看上述 API 的代码,可以发现 update(content) 是将新的样式内容更新到原 style 标签中,而 update() 则是移除注入的 style 标签,那么这里的 module.hot 究竟是什么呢?</p>
@@ -485,33 +327,19 @@ module.hot.dispose(function() {
<p>通过上面的分析,我们就了解了热替换的基本原理,这也解释了为什么我们替换 index1.js 中的输出文本内容时,并没有观察到热更新,而是看到了整个页面的刷新:因为代码中并未包含对热替换插件 API 的调用,代码的解析也没有配置额外能对特定代码调用热替换 API 的 Loader。所以在最后我们就来实现下 JS 中更新文本内容的热替换。</p>
<h3>示例JS 代码中的热替换</h3>
<pre><code>./text.js
export const text = 'Hello World'
./index2.js
import {text} from './text.js'
const div = document.createElement('div')
document.body.appendChild(div)
function render() {
div.innerHTML = text;
}
render()
if (module.hot) {
module.hot.accept('./text.js', function() {
render()
})
export const text = 'Hello World'
./index2.js
import {text} from './text.js'
const div = document.createElement('div')
document.body.appendChild(div)
function render() {
div.innerHTML = text;
}
render()
if (module.hot) {
module.hot.accept('./text.js', function() {
render()
})
}
</code></pre>
<p>在上面的代码中,我们将用于修改的文本单独作为一个 JS 模块,以便传入 hot.accept 方法。当文本发生变更时,可以观察到浏览器端显示最新内容的同时并未触发页面刷新,验证生效。此外, accept 方法也支持监控当前文件的变更,对应的 DOM 更新逻辑稍做调整也能达到无刷新效果,区别在于替换自身模块时示例中不可避免地需要更改 DOM。</p>
@@ -529,12 +357,10 @@ if (module.hot) {
<a href="/专栏/前端工程化精讲-完/03 构建提速:如何正确使用 SourceMap.md.html">下一页</a>
</div>
</div>
</div>
</div>
</div>
</div>
<a class="off-canvas-overlay" onclick="hide_canvas()"></a>
</div>
<script defer src="https://static.cloudflareinsights.com/beacon.min.js/v652eace1692a40cfa3763df669d7439c1639079717194" integrity="sha512-Gi7xpJR8tSkrpF7aordPZQlW2DLtzUlZcumS8dMQjwDHEnw9I7ZLyiOj/6tZStRBGtGgN6ceN6cMH8z7etPGlw==" data-cf-beacon='{"rayId":"70997749bc933cfa","version":"2021.12.0","r":1,"token":"1f5d475227ce4f0089a7cff1ab17c0f5","si":100}' crossorigin="anonymous"></script>
@@ -543,11 +369,9 @@ if (module.hot) {
<script async src="https://www.googletagmanager.com/gtag/js?id=G-NPSEEVD756"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() {
dataLayer.push(arguments);
}
gtag('js', new Date());
gtag('config', 'G-NPSEEVD756');
var path = window.location.pathname
@@ -561,14 +385,12 @@ if (module.hot) {
} else {
setCookie("lastPath", path)
}
function setCookie(cname, cvalue) {
var d = new Date();
d.setTime(d.getTime() + (180 * 24 * 60 * 60 * 1000));
var expires = "expires=" + d.toGMTString();
document.cookie = cname + "=" + cvalue + "; " + expires + ";path = /";
}
function getCookie(cname) {
var name = cname + "=";
var ca = document.cookie.split(';');
@@ -578,7 +400,5 @@ if (module.hot) {
}
return "";
}
</script>
</html>