<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          「Webpack5 專題(二)」靜態(tài)資源的處理

          共 15734字,需瀏覽 32分鐘

           ·

          2021-11-10 08:48

          一、前言

          上一篇講解了?webpack5 的基礎(chǔ)配置。這一篇文章將會介紹如何利用 webpack 中的?Loaders?對靜態(tài)資源做處理,Loaders 是 webpack 的核心概念之一。

          靜態(tài)資源主要包括以下幾方面的內(nèi)容:

          • 樣式文件(CSS)
          • 圖片(Images)
          • 字體(Fonts)
          • 數(shù)據(jù)文件(Data)
          • ...

          文件結(jié)構(gòu):

          webpack
          |-?/dist
          ?|-?index.html
          |-?/
          src
          ?|-?/assets
          ??|-?/
          fonts
          ???|-?font-a.otf
          ???|-?font-b.ttf
          ???|-?font-c.woff
          ???|-?font-d.woff2
          ???|-?font-e.svg
          ??|-?/icons
          ???|-?icon-a.png
          ???|-?incon-b.svg
          ??|-?/im
          ages
          ???|-?img-a.png
          ???|-?img-b.jpg
          ???|-?img-gif.jpg
          ??|-?/js
          ???|-?js-a.js
          ??|-?/
          others
          ???|-?o-a.txt
          ???|-?o-b.xml
          ??|-?/styles
          ???|-?global.scss
          ???|-?reset.css
          ?|-?/
          components
          ??|-?content.js
          ??|-?header.js
          ??|-?sidebar.js
          |-?index.js
          |-?package.json
          |-?webpack.config.js
          復(fù)制代碼

          assets 文件夾中存放了若干靜態(tài)文件(例如:字體、圖標(biāo)、圖片、文本、樣式以及 JS 文件),中間根據(jù)文件的不同,又分了幾個文件夾。這里為了方便起見,文件名均已作簡化處理。

          index.js

          //?js?模塊
          const?Header?=?require("./components/header");
          const?Sidebar?=?require("./components/sidebar");
          const?Content?=?require("./components/content");
          //?圖片模塊?(這?5?個都是小圖)
          const?icon1?=?require("./assets/icons/mac-os.png");
          const?icon2?=?require("./assets/icons/apple-tv.png");
          const?icon3?=?require("./assets/icons/apple-contacts.png");
          const?iconSvg1?=?require("./assets/icons/arrow-up.svg");
          const?iconSvg2?=?require("./assets/icons/arrow-down.svg");
          //?圖片模塊?(這?3?個都是大圖)
          const?dog1?=?require("./assets/images/animal-dog-1.png");
          const?avatar1?=?require("./assets/images/avatar-1.jpg");
          const?cat1?=?require("./assets/images/express-cat-1.gif");
          //?數(shù)據(jù)模塊
          const?fileTxt?=?require("./assets/data/notes.txt");
          const?fileXml?=?require("./assets/data/hello.xml");
          //?字體模塊
          const?font?=?require("./assets/fonts/Calibre-Regular.otf");
          const?iconFont1?=?require("./assets/fonts/iconfont.ttf");
          const?iconFont2?=?require("./assets/fonts/iconfont.woff");
          const?iconFont3?=?require("./assets/fonts/iconfont.woff2");
          //?樣式模塊
          //?const?reset?=?require('./assets/styles/reset.css');
          //?const?global?=?require('./assets/styles/global.scss');

          const?dom?=?document.getElementById("root");

          //?header
          new?Header(dom);
          //?side-bar
          new?Sidebar(dom);
          //?content
          new?Content(dom);
          復(fù)制代碼

          引入了各種文件模塊并放入變量中,每一個模塊在打包以后都有值,可以正常使用。

          二、Loaders — 加載器

          webpack enables use of?loaders[2]?to preprocess files. This allows you to bundle any static resource way beyond JavaScript. You can easily write your own loaders using Node.js.

          簡單來說,loaders 可以幫我們預(yù)處理任何靜態(tài)文件并打包。

          例如:圖片文件,樣式文件、html 文件,甚至是一些數(shù)據(jù)文件:txt 文件、xml 文件……

          那么,如何配置呢?

          三、Asset Modules — 靜態(tài)資源模塊

          根據(jù) Webpack5 的文檔,它簡化了之前版本對于文件方面的配置,提供了?Asset Modules[3]?(靜態(tài)資源模塊),替代了之前常用的?raw-loader、url-loader、file-loader。

          也就是說不用再安裝這幾個 loader 了,直接通過一行type: 'asset'?搞定,書寫更加方便!(注意 module 中 type 的設(shè)置?。?/strong>

          //?webpack?配置文件
          const?path?=?require("path");

          module.exports?=?{
          ??mode:?"production",
          ??entry:?{
          ????main:?"./src/index.js",
          ??},
          ??output:?{
          ????path:?path.resolve(__dirname,?"dist"),
          ????filename:?"bundle.js",
          ??},
          ??//?***?模塊選項中匹配的文件會通過 loaders 來轉(zhuǎn)換!
          ??module:?{
          ????rules:?[
          ??????//?圖片文件
          ??????{
          ????????test:?/\.(jpe?g|png|gif|svg)$/i,
          ????????type:?"asset",?//?一般會轉(zhuǎn)換為?"asset/resource"
          ??????},
          ??????//?字體文件
          ??????{
          ????????test:?/\.(otf|eot|woff2?|ttf|svg)$/i,
          ????????type:?"asset",?//?一般會轉(zhuǎn)換為?"asset/inline"
          ??????},
          ??????//?數(shù)據(jù)文件
          ??????{
          ????????test:?/\.(txt|xml)$/i,
          ????????type:?"asset",?//?一般會轉(zhuǎn)換成?"asset/source"
          ??????},
          ????],
          ??},
          };
          復(fù)制代碼

          每次打包后,文件都會根據(jù) output 的配置放進輸出文件夾,但是對于壓縮處理的文件則不會被打包到文件夾,只會以base64 編碼格式或者 URI 編碼等格式存在于 bundle.js 的源碼中。

          • 源碼中的 base64
          image-20210725202916049.png
          • 源碼中的 URI
          image-20210725203031020.png

          默認(rèn)情況下,當(dāng)文件小于 8 kb 則會采用 base64 編碼,那么上面出現(xiàn)的 URI 編碼怎么設(shè)置的呢?

          1. 特殊處理

          某些文件需要特殊處理。例如,SVG 文件轉(zhuǎn)換為 URI 編碼后,與 base64 相比,體積會更??;

          處理 txt、xml 文件?type: 'asset/source'?更好,它會導(dǎo)出資源的源碼,這樣就能看到全貌,而非 base64 格式的編碼字符串。

          最小化 SVG 文件需要安裝一個第三方庫:mini-svg-data-uri[4].

          npm?i?-D?mini-svg-data-uri
          復(fù)制代碼

          安裝之后,重新配置如下:

          //?webpack?配置文件
          const?path?=?require("path");
          const?miniSVGDataURI?=?require("mini-svg-data-uri");

          module.exports?=?{
          ??//?...
          ??module:?{
          ????rules:?[
          ??????//?圖片文件
          ??????{
          ????????test:?/\.(jpe?g|png|gif)$/i,
          ????????type:?"asset",
          ??????},
          ??????//?svg文件
          ??????{
          ????????test:?/\.svg$/i,
          ????????type:?"asset/inline",
          ????????generator:?{
          ??????????dataUrl(content)?{
          ????????????content?=?content.toString();
          ????????????return?miniSVGDataURI(content);
          ??????????},
          ????????},
          ??????},
          ??????//?字體文件
          ??????{
          ????????test:?/\.(otf|eot|woff2?|ttf|svg)$/i,
          ????????type:?"asset",
          ??????},
          ??????//?數(shù)據(jù)文件
          ??????{
          ????????test:?/\.(txt|xml)$/i,
          ????????type:?"asset/source",
          ??????},
          ????],
          ??},
          };
          復(fù)制代碼

          至此,打包完成?,F(xiàn)在,看看這些文件模塊究竟被打包成什么數(shù)據(jù)了,在 index.js 文件中添加如下代碼:

          //?js?模塊
          const?Header?=?require("./components/header");
          const?Sidebar?=?require("./components/sidebar");
          const?Content?=?require("./components/content");
          //?圖片模塊?(這?5?個都是小圖)
          const?icon1?=?require("./assets/icons/mac-os.png");
          const?icon2?=?require("./assets/icons/apple-tv.png");
          const?icon3?=?require("./assets/icons/apple-contacts.png");
          const?iconSvg1?=?require("./assets/icons/arrow-up.svg");
          const?iconSvg2?=?require("./assets/icons/arrow-down.svg");
          //?圖片模塊?(這?3?個都是大圖)
          const?dog1?=?require("./assets/images/animal-dog-1.png");
          const?avatar1?=?require("./assets/images/avatar-1.jpg");
          const?cat1?=?require("./assets/images/express-cat-1.gif");
          //?其他文件模塊
          const?fileTxt?=?require("./assets/data/notes.txt");
          const?fileXml?=?require("./assets/data/hello.xml");
          //?字體模塊
          const?font?=?require("./assets/fonts/Calibre-Regular.otf");
          const?iconFont1?=?require("./assets/fonts/iconfont.ttf");
          const?iconFont2?=?require("./assets/fonts/iconfont.woff");
          const?iconFont3?=?require("./assets/fonts/iconfont.woff2");
          //?樣式模塊
          //?const?reset?=?require('./assets/styles/reset.css');
          //?const?global?=?require('./assets/styles/global.scss');

          //?在控制臺中打印這些模塊:
          console.log("icon-png:?",?icon1);
          console.log("icon-svg:?",?iconSvg1);
          console.log("png:?",?dog1);
          console.log("jpg:?",?avatar1);
          console.log("gif:?",?cat1);
          console.log("txt:?",?fileTxt);
          console.log("xml:?",?fileXml);
          console.log("font:?",?font);
          console.log("iconFont:?",?iconFont1);

          const?dom?=?document.getElementById("root");

          //?插入一張圖片
          const?img?=?new?Image();
          img.src?=?dog1;?//?圖片模塊?dog1?作為?img?變量的?src?屬性值
          img.width?=?200;
          root.append(img);

          //?header
          new?Header(dom);
          //?side-bar
          new?Sidebar(dom);
          //?content
          new?Content(dom);
          復(fù)制代碼

          瀏覽器頁面展示如下:

          可以看到 SVG 文件?(icon-svg)?是被處理成 URI 編碼的!

          2. 配置靜態(tài)文件名

          默認(rèn)情況下,打包以后的文件是散在 dist 文件夾中的,難以區(qū)分和維護。

          現(xiàn)在,需要將他們分門別類地放進對應(yīng)的文件夾中,就需要對文件名做統(tǒng)一的管理。

          webpack.config.js

          const?path?=?require("path");
          const?miniSVGDataURI?=?require("mini-svg-data-uri");

          module.exports?=?{
          ??mode:?"production",
          ??entry:?{
          ????main:?"./src/index.js",
          ??},
          ??output:?{
          ????path:?path.resolve(__dirname,?"dist"),
          ????filename:?"bundle.js",
          ????//?靜態(tài)文件打包后的路徑及文件名(默認(rèn)是走全局的,如果有獨立的設(shè)置就按照自己獨立的設(shè)置來。)
          ????assetModuleFilename:?"assets/[name]_[hash][ext]",
          ??},
          ??module:?{
          ????rules:?[
          ??????//?圖片文件
          ??????{
          ????????test:?/\.(jpe?g|png|gif)$/i,
          ????????type:?"asset",
          ????????generator:?{
          ??????????filename:?"images/[name]_[hash][ext]",?//?獨立的配置
          ????????},
          ??????},
          ??????//?svg?文件
          ??????{
          ????????test:?/\.svg$/i,
          ????????type:?"asset",
          ????????generator:?{
          ??????????dataUrl(content)?{
          ????????????content?=?content.toString();
          ????????????return?miniSVGDataURI(content);
          ??????????},
          ????????},
          ??????},
          ??????//?字體文件
          ??????{
          ????????test:?/\.(otf|eot|woff2?|ttf|svg)$/i,
          ????????type:?"asset",
          ????????generator:?{
          ??????????filename:?"fonts/[name]_[hash][ext]",
          ????????},
          ??????},
          ??????//?數(shù)據(jù)文件
          ??????{
          ????????test:?/\.(txt|xml)$/i,
          ????????type:?"asset/source",?//?exports?the?source?code?of?the?asset
          ??????},
          ????],
          ??},
          };
          復(fù)制代碼

          第 23 - 25 行,用于單獨配置靜態(tài)文件名;

          generator:?{
          ??filename:?'images/[name]_[hash][ext]'?//?單獨配置打包的路徑及文件名
          },
          復(fù)制代碼

          第 12 行,assetModuleFilename: 'assets/[name][ext]',?用于設(shè)置全局的靜態(tài)文件路徑及文件名。如果文件模塊沒有單獨進行配置,就按照這個來設(shè)置文件名。

          其中,[name]?表示原來的文件名,[hash]?表示散列值,[ext]?表示文件后綴。這些都屬于占位符(placeholders),在 webpack4 中有提到:v4.webpack.js.org/loaders/fil…[5]

          3. asset 類型

          當(dāng) type 設(shè)置為'asset',就會按照以下的策略去打包文件:

          • 如果一個模塊大小超過 8 kb(這個值是默認(rèn)的),就使用?asset/resource,被打包進輸出文件夾中。(類似于 file-loader)
          • 否則,就使用?asset/inline,內(nèi)聯(lián)到打包文件中。(類似于 url-loader)

          區(qū)別在于:前者會被單獨放進輸出文件夾中,后者被處理成 base64 編碼字符串內(nèi)斂進打包出的 JS 文件中。

          后者的好處在于減少一次 http 請求,但是過長的字符串也會加重 js 的體積導(dǎo)致加載變慢,因此需要根據(jù)實際情況來確定到底采用哪一種方式去處理文件。

          注意,當(dāng)被作為后者處理時,是可以設(shè)置編碼方式的,例如上面提到的特殊處理。

          手動通過?`Rule.parser.dataUrlCondition.maxSize`[6]?去設(shè)置兩者的界限:

          {
          ??test:?/\.(jpe?g|png|gif)$/i,
          ??type:?'asset',
          ??generator:?{
          ????filename:?'images/[name]_[hash][ext]',
          ??},
          ??parser:?{
          ????dataUrlCondition:?{
          ??????maxSize:?8?*?1024?//?8kb?(低于8kb都會壓縮成?base64)
          ????}
          ??},
          },
          {
          ??test:?/\.svg$/i,
          ??type:?'asset',
          ??generator:?{
          ????filename:?'icons/[name]_[hash][ext]',
          ????dataUrl(content)?{
          ??????content?=?content.toString();
          ??????return?miniSVGDataURI(content);?//?通過插件提供的編碼算法處理文件
          ????}
          ??},
          ??parser:?{
          ????dataUrlCondition:?{
          ??????maxSize:?2?*?1024?//?2kb?(低于2kb都會壓縮)
          ????}
          ??},
          },
          復(fù)制代碼

          另外,除了asset/resource、asset/inline,還有一個上文提到的,用于處理 txt、xml 文件的asset/source,它相當(dāng)于 webpack4 的 raw-loader。

          三、樣式文件的處理

          1. style-loader & css-loader

          style-loader 和 css-loader 是相輔相成的。

          • style-loader:將?
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                    <th id="afajh"><progress id="afajh"></progress></th>
                  成人在线免费网站 | 精品h片| 操逼片网站 | 一般男女中文字幕 | 亚洲69视频 |