初學(xué)者應(yīng)該看的 Webpack 完整指南(2020)
我們應(yīng)該學(xué)習(xí) webpack 嗎 ?
如今,CLI工具(如create-react-app或Vue -cli)已經(jīng)為我們抽象了大部分配置,并提供了合理的默認(rèn)設(shè)置。
即使那樣,了解幕后工作原理還是有好處的,因?yàn)槲覀冞t早需要對(duì)默認(rèn)值進(jìn)行一些調(diào)整。
在本文中中,我們會(huì)知道 webpack可以做什么,以及如何配置它以滿足我們的日常需求。
什么是 webpack?
作為前端開(kāi)發(fā)人員,我們應(yīng)該熟悉 module 概念。你可能聽(tīng)說(shuō)過(guò) AMD模塊,UMD,Common JS還有ES模塊。
webpack是一個(gè)模塊綁定器,它對(duì)模塊有一個(gè)更廣泛的定義,對(duì)于webpack來(lái)說(shuō),模塊是:
- Common JS modules
- AMD modules
- CSS import
- Images url
- ES modules
webpack 還可以從這些模塊中獲取依賴關(guān)系。
webpack 的最終目標(biāo)是將所有這些不同的源和模塊類(lèi)型統(tǒng)一起來(lái),從而將所有內(nèi)容導(dǎo)入JavaScript代碼,并最生成可以運(yùn)行的代碼。
entry
Webpack的 **entry(入口點(diǎn))**是收集前端項(xiàng)目的所有依賴項(xiàng)的起點(diǎn)。實(shí)際上,這是一個(gè)簡(jiǎn)單的 JavaScript 文件。
這些依賴關(guān)系形成一個(gè)依賴關(guān)系圖。
Webpack 的默認(rèn)入口點(diǎn)(從版本4開(kāi)始)是src/index.js,它是可配置的。webpack 可以有多個(gè)入口點(diǎn)。
Output
output是生成的JavaScript和靜態(tài)文件的地方。
Loaders
Loaders 是第三方擴(kuò)展程序,可幫助webpack處理各種文件擴(kuò)展名。例如,CSS,圖像或txt文件。
Loaders的目標(biāo)是在模塊中轉(zhuǎn)換文件(JavaScript以外的文件)。文件成為模塊后,webpack可以將其用作項(xiàng)目中的依賴項(xiàng)。
Plugins
插件是第三方擴(kuò)展,可以更改webpack的工作方式。例如,有一些用于提取HTML,CSS或設(shè)置環(huán)境變量的插件。
Mode
webpack 有兩種操作模式:開(kāi)發(fā)(development)和生產(chǎn)(production)。它們之間的主要區(qū)別是生產(chǎn)模式自動(dòng)生成一些優(yōu)化后的代碼。
Code splitting
代碼拆分或延遲加載是一種避免生成較大包的優(yōu)化技術(shù)。
通過(guò)代碼拆分,開(kāi)發(fā)人員可以決定僅在響應(yīng)某些用戶交互時(shí)加載整個(gè)JavaScript塊,比如單擊或路由更改(或其他條件)。
被拆分的一段代碼稱(chēng)為 chunk。
Webpack入門(mén)
開(kāi)始使用webpack時(shí),先創(chuàng)建一個(gè)新文件夾,然后進(jìn)入該文件中,初始化一個(gè)NPM項(xiàng)目,如下所示:
- mkdir webpack-tutorial && cd $_
- npm init -y
接著安裝 webpack,webpack-cli和 webpack-dev-server:
- npm i webpack webpack-cli webpack-dev-server --save-dev
要運(yùn)行 webpack,只需要在 package.json 配置如下命令即可:
- "scripts": {
- "dev": "webpack --mode development"
- },
通過(guò)這個(gè)腳本,我們指導(dǎo)webpack在開(kāi)發(fā)模式下工作,方便在本地工作。
Webpack 的第一步
在開(kāi)發(fā)模式下運(yùn)行 webpack:
- npm run dev
運(yùn)行完后會(huì)看到如下錯(cuò)誤:
- ERROR in Entry module not found: Error: Can't resolve './src'
webpack 在這里尋找默認(rèn)入口點(diǎn)src/index.js,所以我們需要手動(dòng)創(chuàng)建一下,并輸入一些內(nèi)容:
- mkdir src
- echo 'console.log("Hello webpack!")' > src/index.js
現(xiàn)在再次運(yùn)行npm run dev,錯(cuò)誤就沒(méi)有了。運(yùn)行的結(jié)果生成了一個(gè)名為dist/的新文件夾,其中包含一個(gè)名為main.js的 JS 文件:
- dist
- └── main.js
這是我們的第一個(gè)webpack包,也稱(chēng)為output。
配置 Webpack
對(duì)于簡(jiǎn)單的任務(wù),webpack無(wú)需配置即可工作,但是很快我們就會(huì)遇到問(wèn)題,一些文件如果沒(méi)有指定的 loader 是沒(méi)法打包的。所以,我們需要對(duì) webpack進(jìn)行配置,對(duì)于 webpack 的配置是在 webpack.config.js 進(jìn)行的,所以我們需要?jiǎng)?chuàng)建該文件:
- touch webpack.config.js
Webpack 用 JavaScript 編寫(xiě),并在無(wú)頭 JS 環(huán)境(例如Node.js)上運(yùn)行。在此文件中,至少需要一個(gè)module.exports,這是的 Common JS 導(dǎo)出方式:
- module.exports = {
- //
- };
在webpack.config.js中,我們可以通過(guò)添加或修改來(lái)改變webpack的行為方式
- entry point
- output
- loaders
- plugins
- code splitting
例如,要更改入口路徑,我們可以這樣做
- const path = require("path");
- module.exports = {
- entry: { index: path.resolve(__dirname, "source", "index.js") }
- };
現(xiàn)在,webpack 將在source/index.js中查找要加載的第一個(gè)文件。要更改包的輸出路徑,我們可以這樣做:
- const path = require("path");
- module.exports = {
- output: {
- path: path.resolve(__dirname, "build")
- }
- }
這樣,webpack將把最終生成包放在build中,而不是dist.(為了簡(jiǎn)單起見(jiàn),在本文中,我們使用默認(rèn)配置)。
打包 HTML
沒(méi)有HTML頁(yè)面的Web應(yīng)用程序幾乎沒(méi)有用。要在webpack中使用 HTML,我們需要安裝一個(gè)插件html-webpack-plugin:
- npm i html-webpack-plugin --save-dev
一旦插件安裝好,我們就可以對(duì)其進(jìn)行配置:
- const HtmlWebpackPlugin = require("html-webpack-plugin");
- const path = require("path");
- module.exports = {
- plugins: [
- new HtmlWebpackPlugin({
- template: path.resolve(__dirname, "src", "index.html")
- })
- ]
- };
這里的意思是讓 webpack,從 src/index.html 加載 HTML 模板。
html-webpack-plugin的最終目標(biāo)有兩個(gè):
- 加載 html 文件
- 它將bundle注入到同一個(gè)文件中
接著,我們需要在 src/index.html 中創(chuàng)建一個(gè)簡(jiǎn)單的 HTML 文件:
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Webpack tutorial</title>
- </head>
- <body>
- </body>
- </html>
稍后,我們會(huì)運(yùn)行這個(gè)程序。
webpack development server
在本文第一部分中,我們安裝了webpack-dev-server。如果你忘記安裝了,現(xiàn)在可以運(yùn)行下面命令安裝一下:
- npm i webpack-dev-server --save-dev
webpack-dev-server 可以讓開(kāi)發(fā)更方便,不需要改動(dòng)了文件就去手動(dòng)刷新文件。配置完成后,我們可以啟動(dòng)本地服務(wù)器來(lái)提供文件。
要配置webpack-dev-server,請(qǐng)打開(kāi)package.json并添加一個(gè) “start” 命令:
- "scripts": {
- "dev": "webpack --mode development",
- "start": "webpack-dev-server --mode development --open",
- },
有了 start 命令,我們來(lái)跑一下:
- npm start
運(yùn)行后,默認(rèn)瀏覽器應(yīng)打開(kāi)。在瀏覽器的控制臺(tái)中,還應(yīng)該看到一個(gè) script 標(biāo)簽,引入的是我們的 main.js。
使用 webpack loader
Loader是第三方擴(kuò)展程序,可幫助webpack處理各種文件擴(kuò)展名。例如,有用于 CSS,圖像或 txt 文件的加載程序。
下面是一些 loader 配置介紹:
- module.exports = {
- module: {
- rules: [
- {
- test: /\.filename$/,
- use: ["loader-b", "loader-a"]
- }
- ]
- },
- //
- };
相關(guān)配置以module 關(guān)鍵字開(kāi)始。在module內(nèi),我們?cè)趓ules內(nèi)配置每個(gè)加載程序組或單個(gè)加載程序。
對(duì)于我們想要作為模塊處理的每個(gè)文件,我們用test和use配置一個(gè)對(duì)象
- {
- test: /\.filename$/,
- use: ["loader-b", "loader-a"]
- }
test 告訴 webpack “嘿,將此文件名視為一個(gè)模塊”。use 定義將哪些 loaders 應(yīng)用于些打包的文件。
打包 CSS
要 在webpack 中打包CSS,我們需要至少安裝兩個(gè) loader。Loader 對(duì)于幫助 webpack 了解如何處理.css文件是必不可少的。
要在 webpack 中測(cè)試 CSS,我們需要在 src 下創(chuàng)建一個(gè)style.css文件:
- h1 {
- color: orange;
- }
另外在 src/index.html 添加 h1 標(biāo)簽
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Webpack tutorial</title>
- </head>
- <body>
- <h1>Hello webpack!</h1>
- </body>
- </html>
最后,在src/index.js 中加載 CSS:
在測(cè)試之前,我們需要安裝兩個(gè) loader:
- css-loader:解析 css 代碼中的 url、@import語(yǔ)法像import和require一樣去處理css里面引入的模塊
- style-loader:幫我們直接將css-loader解析后的內(nèi)容掛載到html頁(yè)面當(dāng)中
安裝 loader:
- npm i css-loader style-loader --save-dev
然后在webpack.config.js中配置它們
- const HtmlWebpackPlugin = require("html-webpack-plugin");
- const path = require("path");
- module.exports = {
- module: {
- rules: [
- {
- test: /\.css$/,
- use: ["style-loader", "css-loader"]
- }
- ]
- },
- plugins: [
- new HtmlWebpackPlugin({
- template: path.resolve(__dirname, "src", "index.html")
- })
- ]
- };
現(xiàn)在,如果你運(yùn)行npm start,會(huì)看到樣式表加載在HTML的頭部:
一旦CSS Loader 就位,我們還可以使用MiniCssExtractPlugin提取CSS文件
Webpack Loader 順序很重要!
在webpack中,Loader 在配置中出現(xiàn)的順序非常重要。以下配置無(wú)效:
- //
- module.exports = {
- module: {
- rules: [
- {
- test: /\.css$/,
- use: ["css-loader", "style-loader"]
- }
- ]
- },
- //
- };
此處,“style-loader”出現(xiàn)在 “css-loader” 之前。但是style-loader用于在頁(yè)面中注入樣式,而不是用于加載實(shí)際的CSS文件。
相反,以下配置有效:
- module.exports = {
- module: {
- rules: [
- {
- test: /\.css$/,
- use: ["style-loader", "css-loader"]
- }
- ]
- },
- //
- };
webpack loaders 是從右到左執(zhí)行的。
打包 sass
要在 webpack 中測(cè)試sass,同樣,我們需要在 src 目錄下創(chuàng)建一個(gè) style.scss 文件:
- @import url("https://fonts.googleapis.com/css?family=Karla:weight@400;700&display=swap");
- $font: "Karla", sans-serif;
- $primary-color: #3e6f9e;
- body {
- font-family: $font;
- color: $primary-color;
- }
另外,在src/index.html中添加一些 Dom 元素:
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Webpack tutorial</title>
- </head>
- <body>
- <h1>Hello webpack!</h1>
- <p>Hello sass!</p>
- </body>
- </html>
最后,將 sass 文件加載到src/index.js中:
- import "./style.scss";
- console.log("Hello webpack!");
在測(cè)試之前,我們需要安裝幾個(gè) loader:
- sass-loader:加載 SASS / SCSS 文件并將其編譯為 CSS
- css-loader:解析 css 代碼中的 url、@import語(yǔ)法像import和require一樣去處理css里面引入的模塊
- style-loader:幫我們直接將css-loader解析后的內(nèi)容掛載到html頁(yè)面當(dāng)中
安裝 loader:
- npm i css-loader style-loader sass-loader sass --save-dev
然后在webpack.config.js中配置它們:
- const HtmlWebpackPlugin = require("html-webpack-plugin");
- const path = require("path");
- module.exports = {
- module: {
- rules: [
- {
- test: /\.scss$/,
- use: ["style-loader", "css-loader", "sass-loader"]
- }
- ]
- },
- plugins: [
- new HtmlWebpackPlugin({
- template: path.resolve(__dirname, "src", "index.html")
- })
- ]
- };
注意loader的出現(xiàn)順序:首先是sass-loader,然后是css-loader,最后是style-loader。
現(xiàn)在,運(yùn)行npm start,你應(yīng)該會(huì)在HTML的頭部看到加載的樣式表:
打包現(xiàn)代 JavaScrip
webpack 本身并不知道如何轉(zhuǎn)換JavaScript代碼。 該任務(wù)已外包給babel的第三方 loader,特別是babel-loader。
babel是一個(gè)JavaScript編譯器和“編譯器”。babel 可以將現(xiàn)代JS(es6, es7...)轉(zhuǎn)換為可以在(幾乎)任何瀏覽器中運(yùn)行的兼容代碼。
同樣,要使用它,我們需要安裝一些 Loader:
- babel-core :把 js 代碼分析成 ast ,方便各個(gè)插件分析語(yǔ)法進(jìn)行相應(yīng)的處理
- babel-preset-env:將現(xiàn)代 JS 編譯為ES5
- **babel-loader **:用于 webpack
引入依賴關(guān)系
- npm i @babel/core babel-loader @babel/preset-env --save-dev
接著,創(chuàng)建一個(gè)新文件babel.config.json配置babel,內(nèi)容如下:
- {
- "presets": [
- "@babel/preset-env"
- ]
- }
最后在配置一下 webpack :
- const HtmlWebpackPlugin = require("html-webpack-plugin");
- const path = require("path");
- module.exports = {
- module: {
- rules: [
- {
- test: /\.scss$/,
- use: ["style-loader", "css-loader", "sass-loader"]
- },
- {
- test: /\.js$/,
- exclude: /node_modules/,
- use: ["babel-loader"]
- }
- ]
- },
- plugins: [
- new HtmlWebpackPlugin({
- template: path.resolve(__dirname, "src", "index.html")
- })
- ]
- };
要測(cè)試轉(zhuǎn)換,可以在 src/index.js中編寫(xiě)一些現(xiàn)代語(yǔ)法:
- import "./style.scss";
- console.log("Hello webpack!");
- const fancyFunc = () => {
- return [1, 2];
- };
- const [a, b] = fancyFunc();
現(xiàn)在運(yùn)行npm run dev來(lái)查看dist中轉(zhuǎn)換后的代碼。打開(kāi) dist/main.js并搜索“fancyFunc”:
- \n\nvar fancyFunc = function fancyFunc() {\n return [1, 2];\n};\n\nvar _fancyFunc = fancyFunc(),\n _fancyFunc2 = _slicedToArray(_fancyFunc, 2),\n a = _fancyFunc2[0],\n b = _fancyFunc2[1];\n\n//# sourceURL=webpack:///./src/index.js?"
沒(méi)有babel,代碼將不會(huì)被轉(zhuǎn)譯:
- \n\nconsole.log(\"Hello webpack!\");\n\nconst fancyFunc = () => {\n return [1, 2];\n};\n\nconst [a, b] = fancyFunc();\n\n\n//# sourceURL=webpack:///./src/index.js?");
**注意:**即使沒(méi)有babel,webpack也可以正常工作。僅在執(zhí)行 ES5 代碼時(shí)才需要進(jìn)行代碼轉(zhuǎn)換過(guò)程。
在 Webpack 中使用 JS 的模塊
webpack 將整個(gè)文件視為模塊。但是,請(qǐng)不要忘記它的主要目的:加載ES模塊。
ECMAScript模塊(簡(jiǎn)稱(chēng)ES模塊)是一種JavaScript代碼重用的機(jī)制,于2015年推出,一經(jīng)推出就受到前端開(kāi)發(fā)者的喜愛(ài)。在2015之年,JavaScript 還沒(méi)有一個(gè)代碼重用的標(biāo)準(zhǔn)機(jī)制。多年來(lái),人們對(duì)這方面的規(guī)范進(jìn)行了很多嘗試,導(dǎo)致現(xiàn)在有多種模塊化的方式。
你可能聽(tīng)說(shuō)過(guò)AMD模塊,UMD,或CommonJS,這些沒(méi)有孰優(yōu)孰劣。最后,在ECMAScript 2015中,ES 模塊出現(xiàn)了。
我們現(xiàn)在有了一個(gè)“正式的”模塊系統(tǒng)。
要在 webpack 使用 ES module ,首先創(chuàng)建 src/common/usersAPI.js 文件:
- const ENDPOINT = "https://jsonplaceholder.typicode.com/users/";
- export function getUsers() {
- return fetch(ENDPOINT)
- .then(response => {
- if (!response.ok) throw Error(response.statusText);
- return response.json();
- })
- .then(json => json);
- }
在 src/index.js中,引入上面的模塊:
- import { getUsers } from "./common/usersAPI";
- import "./style.scss";
- console.log("Hello webpack!");
- getUsers().then(json => console.log(json));
生產(chǎn)方式
如前所述,webpack有兩種操作模式:開(kāi)發(fā)(development )和(production)。到目前為止,我們僅在開(kāi)發(fā)模式下工作。
在開(kāi)發(fā)模式中,為了便于代碼調(diào)試方便我們快速定位錯(cuò)誤,不會(huì)壓縮混淆源代碼。相反,在生產(chǎn)模式下,webpac k進(jìn)行了許多優(yōu)化:
- 使用 TerserWebpackPlugin 進(jìn)行縮小以減小 bundle 的大小
- 使用ModuleConcatenationPlugin提升作用域
在生產(chǎn)模式下配 置webpack,請(qǐng)打開(kāi) package.json 并添加一個(gè)“ build” 命令:
現(xiàn)在運(yùn)行 npm run build,webpack 會(huì)生成一個(gè)壓縮的包。
Code splitting
**代碼拆分(Code splitting)**是指針對(duì)以下方面的優(yōu)化技術(shù):
- 避免出現(xiàn)一個(gè)很大的 bundle
- 避免重復(fù)的依賴關(guān)系
webpack 社區(qū)考慮到應(yīng)用程序的初始 bundle 的最大大小有一個(gè)限制:200KB。
在 webpack 中有三種激活 code splitting 的主要方法:
- 有多個(gè)入口點(diǎn)
- 使用 optimization.splitChunks 選項(xiàng)
- 動(dòng)態(tài)導(dǎo)入
第一種基于多個(gè)入口點(diǎn)的技術(shù)適用于較小的項(xiàng)目,但是從長(zhǎng)遠(yuǎn)來(lái)看它是不可擴(kuò)展的。這里我們只關(guān)注第二和第三種方式。
Code splitting 與 optimization.splitChunks
考慮一個(gè)使用Moment.js 的 JS 應(yīng)用程序,Moment.js是流行的時(shí)間和日期JS庫(kù)。
在項(xiàng)目文件夾中安裝該庫(kù):
- npm i moment
現(xiàn)在清除src/index.js的內(nèi)容,并引入 moment 庫(kù):
- import moment from "moment";
運(yùn)行 npm run build 并查看控制的輸出內(nèi)容:
- main.js 350 KiB 0 [emitted] [big] main
整個(gè) moment 庫(kù)都綁定到了 main.js 中這樣是不好的。借助optimization.splitChunks,我們可以從主包中移出moment.js。
要使用它,需要在 webpack.config.js 添加 optimization 選項(xiàng):
- const HtmlWebpackPlugin = require("html-webpack-plugin");
- const path = require("path");
- module.exports = {
- module: {
- // ...
- },
- optimization: {
- splitChunks: { chunks: "all" }
- },
- // ...
- };
運(yùn)行npm run build 并查看運(yùn)行結(jié)果:
- main.js 5.05 KiB 0 [emitted] main
- main.js 346 KiB 1 [emitted] [big] vendors~main
現(xiàn)在,我們有了一個(gè)帶有moment.js 的vendors〜main.js,而主入口點(diǎn)的大小更合理。
注意:即使進(jìn)行代碼拆分,moment.js仍然是一個(gè)體積較大的庫(kù)。有更好的選擇,如使用luxon或date-fns。
## Code splitting 與 動(dòng)態(tài)導(dǎo)入
Code splitting的一種更強(qiáng)大的技術(shù)使用動(dòng)態(tài)導(dǎo)入來(lái)有條件地加載代碼。在ECMAScript 2020中提供此功能之前,webpack 提供了動(dòng)態(tài)導(dǎo)入。
這種方法在 Vue 和 React 之類(lèi)的現(xiàn)代前端庫(kù)中得到了廣泛使用(React有其自己的方式,但是概念是相同的)。
Code splitting 可用于:
- 模塊級(jí)別
- 路由級(jí)別
例如,你可以有條件地加載一些 JavaScript 模塊,以響應(yīng)用戶的交互(例如單擊或鼠標(biāo)移動(dòng))?;蛘?,可以在響應(yīng)路由更改時(shí)加載代碼的相關(guān)部分。
要使用動(dòng)態(tài)導(dǎo)入,我們先清除src/index.html,并寫(xiě)入下面的內(nèi)容:
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Dynamic imports</title>
- </head>
- <body>
- <button id="btn">Load!</button>
- </body>
- </html>
在 src/common/usersAPI.js中:
- const ENDPOINT = "https://jsonplaceholder.typicode.com/users/";
- export function getUsers() {
- return fetch(ENDPOINT)
- .then(response => {
- if (!response.ok) throw Error(response.statusText);
- return response.json();
- })
- .then(json => json);
- }
在 src/index.js 中
- const btn = document.getElementById("btn");
- btn.addEventListener("click", () => {
- //
- });
如果運(yùn)行npm run start查看并單擊界面中的按鈕,什么也不會(huì)發(fā)生。
現(xiàn)在想象一下,我們想在某人單擊按鈕后加載用戶列表。“原生”的方法可以使用靜態(tài)導(dǎo)入從src/common /usersAPI.js加載函數(shù):
- import { getUsers } from "./common/usersAPI";
- const btn = document.getElementById("btn");
- btn.addEventListener("click", () => {
- getUsers().then(json => console.log(json));
- });
問(wèn)題在于ES模塊是靜態(tài)的,這意味著我們無(wú)法在運(yùn)行時(shí)更改導(dǎo)入的內(nèi)容。
通過(guò)動(dòng)態(tài)導(dǎo)入,我們可以選擇何時(shí)加載代碼
- const getUserModule = () => import("./common/usersAPI");
- const btn = document.getElementById("btn");
- btn.addEventListener("click", () => {
- getUserModule().then(({ getUsers }) => {
- getUsers().then(json => console.log(json));
- });
- });
這里我們創(chuàng)建一個(gè)函數(shù)來(lái)動(dòng)態(tài)加載模塊
- const getUserModule = () => import("./common/usersAPI");
現(xiàn)在,當(dāng)你第一次使用npm run start加載頁(yè)面時(shí),會(huì)看到控制臺(tái)中已加載 js 包:
現(xiàn)在,僅在單擊按鈕時(shí)才加載/common/usersAPI:
對(duì)應(yīng)的 chunk 是 0.js
通過(guò)在導(dǎo)入路徑前面加上魔法注釋/ * webpackChunkName:“ name_here” * /,可以更改塊名稱(chēng):
- const getUserModule = () =>
- import(/* webpackChunkName: "usersAPI" */ "./common/usersAPI");
- const btn = document.getElementById("btn");
- btn.addEventListener("click", () => {
- getUserModule().then(({ getUsers }) => {
- getUsers().then(json => console.log(json));
- });
- });
作者:Valentino Gagliardi 譯者:前端小智 來(lái)源:valentinog 原文:https://www.sitepoint.com/webpack-beginner-guide/
本文轉(zhuǎn)載自微信公眾號(hào)「大遷世界」,可以通過(guò)以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系大遷世界公眾號(hào)。