<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>

          一文徹底解決新手對 webpack 的恐懼!

          共 26359字,需瀏覽 53分鐘

           ·

          2022-05-05 10:10

          網(wǎng)上太多文章并不適合新手學(xué)習(xí),甚至?xí)屗麄儗ebpack、對一些插件產(chǎn)生誤解,所以我決定要寫一篇能讓新手不在害怕webpack的文章。

          前言、你必須知道的知識 是非常重要的,務(wù)必認(rèn)真閱讀!

          前言

          首先拋出結(jié)論,webpack是一個(gè)非常簡單的工具,毫無難度可言。webpack阻礙很多人的根本原因是大家對一些概念的不熟悉、對webpack豐富的loader和plugin望而怯步。當(dāng)你把概念弄清楚后,你自然而然的就知道自己需要什么loader和plugin了。

          看完后你一定會說:“就這?webpack就這?”。

          個(gè)人建議:例如create-react-app就是一個(gè)很好的腳手架,你可以寫不出這樣的腳手架,但你一定要能看懂,在你有需要的時(shí)候有能力去修改源碼。webpack掌握到這個(gè)程度很多時(shí)候就完全夠用了。在最后我還會補(bǔ)充如何自己寫一個(gè)loader和plugin(不過我相信不用到最后,認(rèn)真閱讀的你就已經(jīng)知道要如何編寫了)

          準(zhǔn)備環(huán)境、版本

          node: ^12.16.1

          webpack: ^4.44.2

          webpack-cli: ^3.3.12

          webpack5升級了一些新特性,所以我們這篇文章以目前常用的webpack4來講解。不過完全不用擔(dān)心都出5了怎么還學(xué)4的問題,道理都是相通的,4都會了,5它不就是多點(diǎn)新特性了嗎。

          你必須知道的知識

          webpack概念

          webpack是一個(gè)現(xiàn)代JavaScript應(yīng)用程序的靜態(tài)模塊打包器。如果你接觸js夠早的話,你一定知道最初的工程可沒有這樣的打包工具,一個(gè)文件就相當(dāng)于一個(gè)模塊,最終這些文件需要按照一定的順序使用script標(biāo)簽引入html(因?yàn)槿绻樞虿粚蜁?dǎo)致依賴變量丟失等錯(cuò)誤問題)。

          但是這個(gè)寫項(xiàng)目不僅麻煩而且不優(yōu)雅,隨著node.js的出現(xiàn)和發(fā)展,才出現(xiàn)了這類基于node.js運(yùn)行的打包工具(gulp、grunt,以及現(xiàn)在最流行的webpack),因?yàn)閚ode.js擁有可對文件操作的能力。所以webpack本質(zhì)就是為我們打包js的引用,而我們常聽到各種loader、各種plugin、熱更新、熱模塊替換等等都是webpack的一個(gè)升華,使得webpack能為我們提供更多的幫助。

          • loader:webpack本身只能打包js和json格式的文件,但實(shí)際項(xiàng)目中我們還有會css、scss、png、ts等其他文件,這時(shí)我們就需要使用loader來讓它正確打包。

            • 總結(jié):loader是處理編譯js和json以外的文件時(shí)用的
            • 常見的loader:

          style-loader??
          css-loader??
          sass-loader??
          ts-loader??
          file-loader??
          babel-loader??
          postcss-loader??
          ...????

          plugin:plugin可以在webpack運(yùn)行到某個(gè)階段時(shí)候,幫你做一些事情,類似react/vue中的生命周期。具體的某個(gè)插件(plugin)就是在webpack構(gòu)建過程中的特定時(shí)機(jī)注入擴(kuò)展邏輯來改變構(gòu)建結(jié)果,作用于整個(gè)構(gòu)建過程。

          弄明白這些東西

          • postcss:postcss是一個(gè)用 JavaScript 工具和插件轉(zhuǎn)換 CSS 代碼的工具。你可以把他理解成babel,他本身作用不大,我們很多具體需求的實(shí)現(xiàn)都需要他的插件來完成,他本身更像一個(gè)平臺。

            例如,項(xiàng)目中我們需要webpack自動的幫我們?yōu)閏ss樣式加上兼容性前綴,實(shí)際幫我們加上前綴的插件是autoprefixer[1],但他能為我們加前綴的前提又是我們有postcss。千萬不要把postcss誤解postcss成scss、less替代品

            • 對于“ PostCSS”一詞,我們可以替代地指兩件事:

          1. 該工具本身就是PostCSS[2](運(yùn)行時(shí)會得到什么)npm install postcss,以及
          2. 該工具支持的PostCSS插件生態(tài)系統(tǒng)[3]

          babel:babel 是一個(gè) JavaScript 編譯器,他可以讓我們不再考慮兼容性,盡情的使用下一代的 JavaScript 語法編程。但是要實(shí)現(xiàn)具體的語法轉(zhuǎn)換,我們還是要使用他的插件[4]才能實(shí)現(xiàn)

          • 在babel7后為我們提供了預(yù)設(shè)[5],可以讓我們不再自己麻煩的對插件進(jìn)行組合,想在什么環(huán)境運(yùn)行就寫什么預(yù)設(shè)即可(相當(dāng)于每個(gè)預(yù)設(shè)選項(xiàng)中都幫你組合好了這個(gè)環(huán)境中需要用到的插件)

          es6+語法:babel默認(rèn)會轉(zhuǎn)換語法,例如:let、const、() => {}、class

          es6+特性:babel不會轉(zhuǎn)換特性,特性需要js代碼墊片來兼容低版本的瀏覽器。例如:Iterator、Generator、Set、Map、Proxy、Reflect、Symbol、Promise

          @babel/core:@babel/core是babel的核心庫,所有的核心api都在這個(gè)庫里,這些api可供babel-loader調(diào)用

          @babel/preset-env:這是一個(gè)預(yù)設(shè)的插件集合,包含了一組相關(guān)的插件,Bable中是通過各種插件來指導(dǎo)如何進(jìn)行代碼轉(zhuǎn)換。該插件包含所有es6轉(zhuǎn)化為es5的翻譯規(guī)則

          @babel/polyfill:@babel/preset-env只是提供了語法轉(zhuǎn)換的規(guī)則,但是它并不能彌補(bǔ)瀏覽器缺失的一些新的功能,如一些內(nèi)置的方法和對象,如Promise,Array.from等,此時(shí)就需要polyfill來做js的墊片,彌補(bǔ)低版本瀏覽器缺失的這些新功能。注意:Babel 7.4.0該包將被廢棄

          core-js:它是JavaScript標(biāo)準(zhǔn)庫的polyfill,而且它可以實(shí)現(xiàn)按需加載。使用@babel/preset-env的時(shí)候可以配置core-js的版本和core-js的引入方式。注意:@babel/polyfill依賴core-js

          regenerator-runtime:提供generator函數(shù)的轉(zhuǎn)碼

          補(bǔ)充知識點(diǎn)(重要)

          • browserslist:browserslist實(shí)際上就是聲明了一段瀏覽器的合集,我們的工具可以根據(jù)這個(gè)合集描述,針對性的輸出兼容性代碼,browserslist應(yīng)用于babel、postcss等工具當(dāng)中。

            • browserslist可以在package.json文件配置,也可以單出寫一個(gè).browserslistrc文件進(jìn)行配置

            • 工具會自動查找.browserslistrc中的配置,如果沒有發(fā)現(xiàn).browserslistrc文件,則會去package.json中查找

            • 例子:

              //?在.browserslistrc中的寫法??
              >?1%??
              last?2?versions??

              //?還可以配置不同環(huán)境下的規(guī)則(在.browserslistrc中)??
              [production]??
              >?1%??
              ie?10??

              [development]??
              last?1?chrome?version??
              last?1?firefox?version??

              //?在package.json中的寫法??
              {??
              ??"browserslist":?[">?1%",?"last?2?versions"]??
              }??

              //?還可以配置不同環(huán)境下的規(guī)則(在package.json中)??
              //?production和development取決你webpack中mode字段的配置??
              {??
              ??"browserslist":?{??
              ??"production":?[??
              ??">0.2%",??
              ??"not?dead",??
              ??"not?op_mini?all"??
              ?],??
              ???"development":?[??
              ???"last?1?chrome?version",??
              ???"last?1?firefox?version",??
              ???"last?1?safari?version"??
              ??]??
              ?}??
              ?}??

          ?“> 1%”表示兼容市面上使用量大于百分之一的瀏覽,“l(fā)ast 1 chrome version”表示兼容到谷歌的上一個(gè)版本,具體的可以使用命令npx browserslist "> 1%"的方式查看都包含了哪些瀏覽器,browserslist的github地址[6]
          • chunk:它不是庫也不是插件,它就是一個(gè)名詞,顧名思義就是代碼塊。為什么要單獨(dú)把他拎出來說呢,因?yàn)槟忝靼姿院竽阕匀痪湍芾斫鈝ebpack中配置一些參數(shù)的意思了

          • chunks:一個(gè)chunks至少包含一個(gè)chunk,chunks是多個(gè)chunk的合集

            //?index.js??
            import?{?a?}?from?'a.js'??
            console.log('我是index文件')??

            //a.js??
            const?a?=?'我是a文件'??
            export?{?a?}??

            上面代碼來說,a.js就是chunk,而index.js就是chunks

            在webpack構(gòu)建中入口是chunks,出口是chunk(知道這個(gè)概念就行)

          搭建webpack項(xiàng)目

          初始化項(xiàng)目

          • 新建一個(gè)文件夾

            mkdir?learnWebpack????
          • 進(jìn)入到文件夾中

            cd?learnWebpack/????
          • 初始化package.json文件

            #?可以輸入配置??
            npm?init??

            #?默認(rèn)配置創(chuàng)建??
            npm?init?-y??

            #?是用npm?init?-y后得到的內(nèi)容??
            {??
            ??"name":?"learnwebpack",??
            ??"version":?"1.0.0",??
            ??"description":?"",??
            ??"main":?"index.js",??
            ??"scripts":?{??
            ????"test":?"echo?\"Error:?no?test?specified\"?&&?exit?1"??
            ??},??
            ??"author":?"",??
            ??"license":?"ISC"??
            }??

          安裝

          創(chuàng)建目錄

          • 根目錄下創(chuàng)建src、src下創(chuàng)建index.js

          • 在index.js中添加一段代碼:

            console.log('hello?webpack')????
          • 在package.json文件中的scripts字段中添加"start": "webpack"

            "scripts":?{??
            ??"test":?"echo?\"Error:?no?test?specified\"?&&?exit?1",??
            ??"start":?"webpack"??
            }????
          • 在命令行中執(zhí)行yarn start,我們會發(fā)現(xiàn)編譯成功,但有個(gè)警告!在webpack自動在根目錄下創(chuàng)建了一個(gè)dist文件夾和dist文件夾中的main.js文件

            • 關(guān)于警告:ARNING in configuration The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment. You can also set it to 'none' to disable any default behavior. Learn more: webpack.js.org/configurati…[7]; 警告中已經(jīng)說的很清楚了,我們沒有設(shè)置mode字段。我們只需在webpack的配置中配置mode字段即可消除該警告

            • 關(guān)于dist文件夾和main.js文件 :這是webpack4當(dāng)初宣傳的零配置使用。很顯然我們這里什么都沒配置,就幫我們成功打包了一個(gè)src下的代碼。該功能實(shí)際上是wabpack默認(rèn)幫我們配置了一套簡單的打包配置,讓我們看看webpack默認(rèn)為我們配置了什么:

              const?path?=?require('path')??
              module.exports?=?{??
              ??extry:?'./src/index.js',??
              ??output:?{??
              ????filename:?'main.js',??
              ????path:?path.resolve(__dirname,?'./dist')???
              ??}??
              }??

            • 注意:這份默認(rèn)配置是不是太過簡單了。看了這個(gè)配置后,我想你也知道為什么當(dāng)我們創(chuàng)建的不是src或者src下不是index.js時(shí)候無法使用零配置功能的原因了

          webpack的零配置

          上面我們看到了,零配置很弱,真正的項(xiàng)目中他完全不可能滿足我們的需求

          我們想要自定義配置webpack的話,需要在根目錄上創(chuàng)建一個(gè)webpack.config.js的文件,這個(gè)文件的內(nèi)容可以覆蓋webpack的零配置

          • 使用默認(rèn)的配置文件:webpack.config.js

            #?使用webpack.config.js配置文件時(shí),輸入該命令即可啟動webpack打包??
            webpack????
          • 使用其他配置文件:如yzyConfig.js,可以通過--config yzyConfig.js來指定webpack使用哪個(gè)配置文件來執(zhí)行構(gòu)建

            #?通過--config來指定其他配置文件,并按照指定的配置文件的配置內(nèi)容進(jìn)行打包??
            webpack?--config?yzyConfig.js????

          webpack配置核心概念

          • chunk:指代碼塊,一個(gè)chunk可能由多個(gè)模塊組合而成,也用于代碼合并與分割(這里的合并分割主要指指紋策略的判斷),指紋策略簡單來說就是文件名后的hash

          • bundle:資源經(jīng)過webpack流程解析編譯后最終輸出的成果文件(一個(gè).js格式的文件,也就是我們的output文件)

          • entry:文件打包的入口,webpack會根據(jù)entry遞歸的去尋找依賴,每個(gè)依賴都將被它處理,最后打包到集合文件中

          • output:配置打包輸出的位置、文件名等

          • loader:默認(rèn)情況下,webpack僅支持js和json文件,通過loader,可以讓它解析其他類型的文件。理論上只要有相應(yīng)的loader,webpack可以處理任何類型的文件

          • plugin:loader主要的職責(zé)是讓webpack認(rèn)識更多的文件類型,而plugin的職責(zé)則是讓其可以控制構(gòu)建流程,從而執(zhí)行一些特殊的任務(wù)。插件的功能非常強(qiáng)大,可以完成各種各樣的任務(wù)

          • mode:目標(biāo)環(huán)境,不用的目標(biāo)環(huán)境會影響webpack打包時(shí)的決策

            • production:碼進(jìn)行壓縮等一系列優(yōu)化操作
            • development:有利于熱更新的處理,識別哪個(gè)模塊變化代
            • none:什么都不做,打包時(shí)會有提示警告
          配置webpack.config.js

          項(xiàng)目搭建目標(biāo)

          咱們目標(biāo)不是搭建一個(gè)完整全面的項(xiàng)目工程,目標(biāo)是以一些有代表性的功能作為切入點(diǎn)學(xué)習(xí)webpack,我相信這些你認(rèn)真看過后一定能做到舉一反三

          • 實(shí)現(xiàn)加載css
          • 實(shí)現(xiàn)css效果展示
          • 實(shí)現(xiàn)css前綴自動補(bǔ)充
          • 實(shí)現(xiàn)css以文件形式導(dǎo)出
          • 實(shí)現(xiàn)自動生成html文件
          • 實(shí)現(xiàn)打包清空dist文件夾
          • 實(shí)現(xiàn)圖片在js文件中引入
          • 實(shí)現(xiàn)圖片在css文件中引入
          • 實(shí)現(xiàn)webpack本地服務(wù)
          • 實(shí)現(xiàn)多頁面打包

          實(shí)現(xiàn)加載css

          我們已經(jīng)知道.css文件無法正常被webpack打包進(jìn)bundle(bundle的解釋可查看“webpack配置核心概念”部分)文件,所以我們需要一個(gè)loader作為加載器將它正確打包進(jìn)bundle文件

          文件內(nèi)容

          dcc8a65606c9d5115bbe0785e06d0da9.webp

          安裝css-loader

          yarn?add?css-loader?-D????

          配置css-loader

          const?path?=?require('path')??
          module.exports?=?{??
          ??entry:?'./src/index.js',??
          ??output:?{??
          ????filename:?'main.js',??
          ????path:?path.resolve(__dirname,?'./dist')??
          ??},??
          ??mode:?"development",??
          ??module:?{??
          ????rules:?[??
          ??????{??
          ????????test:?/\.css$/,??
          ????????use:?"css-loader"??
          ??????}??
          ????]??
          ??}??
          }????

          運(yùn)行webpack命令,檢查一下dist/main.js中是否包含了css文件中的內(nèi)容

          9a37afe352ae602ed2c1da5030a36298.webp

          我們發(fā)現(xiàn)css文件的內(nèi)容被成功打包了,這時(shí)如果你在dist文件夾下創(chuàng)建了一個(gè)html頁面給div元素加上了box類,并引入main.js文件,你會發(fā)現(xiàn)完全看不到樣式效果。

          因?yàn)榇藭r(shí)css中的內(nèi)容只是被作為一段字符串引入了js中(相當(dāng)于對css文件的內(nèi)容進(jìn)行了JSON.stringify),所以你自然是看不到效果的。

          想要看到效果要怎么辦?當(dāng)然是將css內(nèi)容放進(jìn)style標(biāo)簽啦!不過這步不需要我們做,因?yàn)槲覀冇衧tyle-loader為我們做這件事情!

          實(shí)現(xiàn)css效果展示

          安裝style-loader

          yarn?add?style-loader?-D????

          配置style-loader

          const?path?=?require('path')??
          module.exports?=?{??
          ??entry:?'./src/index.js',??
          ??output:?{??
          ????filename:?'main.js',??
          ????path:?path.resolve(__dirname,?'./dist')??
          ??},??
          ??mode:?'development',??
          ??module:?{??
          ????rules:?[??
          ??????{??
          ????????test:?/\.css$/,??
          ????????use:?['style-loader',?'css-loader']??
          ??????}??
          ????]??
          ??}??
          }????

          這里需要注意的是,對同一種類型文件使用多個(gè) loader的時(shí)候,use屬性接收一個(gè)數(shù)組,并且從右向左執(zhí)行。所以style-loader要寫在css-loader前面

          運(yùn)行webpack命令,看一下結(jié)果

          62b5986e61cf4b078af8f16b4871e052.webp

          成功!

          但是我們知道,css3在瀏覽器中會存在兼容性問題,我們可以通過給屬性加上前綴來解決該問題。前端豐富的生態(tài)當(dāng)然不會讓你自己傻傻的做這件事情,我們可以通過autoprefixer這個(gè)插件幫我們完成

          實(shí)現(xiàn)css前綴自動補(bǔ)充

          已經(jīng)知道autoprefixer是postcss工具的插件,所以我們需要安裝postcss和postcss-loader

          安裝postcss、postcss-loader、autoprefixer,這里postcss-loader需要指定4.x的版本,因?yàn)?.x的版本和webpack4會存在報(bào)錯(cuò)問題

          [email protected]?postcss?-D????

          配置postcss-loader和插件autoprefixer

          const?path?=?require('path')??
          module.exports?=?{??
          ??entry:?'./src/index.js',??
          ??output:?{??
          ????filename:?'main.js',??
          ????path:?path.resolve(__dirname,?'./dist')??
          ??},??
          ??mode:?'development',??
          ??module:?{??
          ????rules:?[??
          ??????{??
          ????????test:?/\.css$/,??
          ????????use:?[??
          ??????????'style-loader',??
          ??????????'css-loader',??
          ??????????{??
          ????????????loader:?'postcss-loader',??
          ????????????options:?{??
          ??????????????postcssOptions:?{??
          ????????????????plugins:?[require('autoprefixer')]??
          ??????????????}??
          ????????????}??
          ??????????}??
          ????????]??
          ??????}??
          ????]??
          ??}??
          }????

          當(dāng)loader需要寫配置的時(shí)候,我們可以把loader寫成一個(gè)對象,loader屬性就是要使用的loader名稱,options屬性就是這個(gè)loader的配置對象。autoprefixer是postcss的插件,所以autoprefixer的使用自然就要寫在postcss-loader的配置中了

          因?yàn)閜ostcss有自己的配置文件,所以這里還可以寫成這樣:

          //?webpack.config.js??
          const?path?=?require('path')??
          module.exports?=?{??
          ??entry:?'./src/index.js',??
          ??output:?{??
          ????filename:?'main.js',??
          ????path:?path.resolve(__dirname,?'./dist')??
          ??},??
          ??mode:?'development',??
          ??module:?{??
          ????rules:?[??
          ??????{??
          ????????test:?/\.css$/,??
          ????????use:?['style-loader',?'css-loader',?'postcss-loader']??
          ??????}??
          ????]??
          ??}??
          }??
          ??
          //?根目錄下新建postcss.config.js文件??
          module.exports?=?{??
          ??plugins:?[require('autoprefixer')],??
          }????

          這里我們需要配置一下browserslist,否則插件不知道按照什么樣的規(guī)則進(jìn)行前綴補(bǔ)全

          //?在package.json文件中添加??
          //?這里的意思表示目標(biāo)瀏覽器為ie瀏覽器,并需要兼容到ie8以上??
          "browserslist":?["ie?>?8"]????

          運(yùn)行webpack命令看一下結(jié)果

          d4e5000b87a57c7eea6c32904a7823f8.webp

          成功!

          實(shí)現(xiàn)css以文件形式導(dǎo)出

          隨著項(xiàng)目的增大,我們不想把那么多的樣式都放在style標(biāo)簽中,我們想用link標(biāo)簽引入,這時(shí)我們就需要使用mini-css-extract-plugin[8]

          安裝mini-css-extract-plugin

          yarn?add?mini-css-extract-plugin?-D????

          配置mini-css-extract-plugin插件和它的loader,這時(shí)我們不需要style-loader了,我們要style-loader替換成MiniCssExtractPlugin.loader

          const?path?=?require('path')??
          const?MiniCssExtractPlugin?=?require('mini-css-extract-plugin')??
          module.exports?=?{??
          ??entry:?'./src/index.js',??
          ??output:?{??
          ????filename:?'main.js',??
          ????path:?path.resolve(__dirname,?'./dist')??
          ??},??
          ??mode:?'development',??
          ??module:?{??
          ????rules:?[??
          ??????{??
          ????????test:?/\.css$/,??
          ????????use:?[??
          ??????????MiniCssExtractPlugin.loader,??
          ??????????'css-loader',??
          ??????????'postcss-loader'??
          ????????]??
          ??????}??
          ????]??
          ??},??
          ??plugins:?[??
          ????new?MiniCssExtractPlugin({??
          ??????filename:?"css/[name].css"??
          ????})??
          ??]??
          }????
          • MiniCssExtractPlugin可以配置輸出文件名
          • [name]為占位符,引入的時(shí)候是什么名字,導(dǎo)出的時(shí)候就是什么名字
          • css/表示導(dǎo)出到css文件夾下

          運(yùn)行webpack命令看一下結(jié)果

          5c341aafafca7d196f570272c289b434.webp

          成功!

          實(shí)現(xiàn)自動生成html文件

          我們發(fā)現(xiàn)dist下的html是我們自己手動創(chuàng)建的,這顯然不夠優(yōu)雅。html-webpack-plugin[9]幫你解決!

          安裝html-webpack-plugin,這里也要制定一下4.x的版本

          [email protected]?-D????

          配置html-webpack-plugin

          const?path?=?require('path')??
          const?MiniCssExtractPlugin?=?require('mini-css-extract-plugin')??
          const?HtmlWebpackPlugin?=?require('html-webpack-plugin')??
          module.exports?=?{??
          ??entry:?'./src/index.js',??
          ??output:?{??
          ????filename:?'main.js',??
          ????path:?path.resolve(__dirname,?'./dist')??
          ??},??
          ??mode:?'development',??
          ??module:?{??
          ????rules:?[??
          ??????{??
          ????????test:?/\.css$/,??
          ????????use:?[??
          ??????????MiniCssExtractPlugin.loader,??
          ??????????'css-loader',??
          ??????????'postcss-loader'??
          ????????]??
          ??????}??
          ????]??
          ??},??
          ??plugins:?[??
          ????new?MiniCssExtractPlugin({??
          ??????filename:?"css/[name].css",??
          ????}),??
          ????new?HtmlWebpackPlugin({??
          ??????template:?'./src/index.html'??
          ????})??
          ??]??
          }????

          運(yùn)行webpack命令看一下結(jié)果

          46ed973f14b6008dcb3c1054bc4790f1.webp

          成功!很顯然HtmlWebpackPlugin根據(jù)我們的模版為我們生成了新的html頁面,并自動引入了dist包下的依賴。查看更多HtmlWebpackPlugin配置[10]

          實(shí)現(xiàn)打包清空dist文件夾

          我們會發(fā)現(xiàn)每次打包dist文件夾的內(nèi)容會被覆蓋,但是如果下次打包出來的文件名不同,那舊的打包文件還會存在,這是我們不想要的。clean-webpack-plugin[11]來幫我們解決這個(gè)問題

          安裝clean-webpack-plugin

          yarn?add?clean-webpack-plugin?-D????

          配置clean-webpack-plugin

          const?path?=?require('path')??
          const?MiniCssExtractPlugin?=?require('mini-css-extract-plugin')??
          const?HtmlWebpackPlugin?=?require('html-webpack-plugin')??
          const?{?CleanWebpackPlugin?}?=?require('clean-webpack-plugin')??
          module.exports?=?{??
          ??entry:?'./src/index.js',??
          ??output:?{??
          ????filename:?'main.js',??
          ????path:?path.resolve(__dirname,?'./dist')??
          ??},??
          ??mode:?'development',??
          ??module:?{??
          ????rules:?[??
          ??????{??
          ????????test:?/\.css$/,??
          ????????use:?[??
          ??????????MiniCssExtractPlugin.loader,??
          ??????????'css-loader',??
          ??????????'postcss-loader'??
          ????????]??
          ??????}??
          ????]??
          ??},??
          ??plugins:?[??
          ????new?MiniCssExtractPlugin({??
          ??????filename:?"css/[name].css",??
          ????}),??
          ????new?HtmlWebpackPlugin({??
          ??????template:?'./src/index.html'??
          ????}),??
          ????new?CleanWebpackPlugin()??
          ??]??
          }????

          這時(shí),你也在dist文件夾下隨意建一個(gè)其他文件,運(yùn)行webpack命令看一下結(jié)果,你會發(fā)現(xiàn)你隨意建的文件不在了。驗(yàn)證了這一點(diǎn),就說明你成功了

          實(shí)現(xiàn)圖片在js文件中引入

          實(shí)現(xiàn)這個(gè)功能我們使用url-loader,當(dāng)然你也可以使用file-loader。url-loader是file-loader的升級版,它內(nèi)部也依賴了file-loader。file-loader和url-loader在webpack5后都被廢棄了,使用asset modules代替

          安裝url-loader和file-loader

          yarn?add?url-loader?file-loader?-D????

          你可以會疑問為什么要裝file-loader,因?yàn)閡rl-loader依賴file-loader。若不裝,當(dāng)url-loader將圖片轉(zhuǎn)換為base64導(dǎo)入bundle時(shí)不會存在問題,但直接輸出圖片到dist文件夾下就會報(bào)錯(cuò),告訴你缺少file-loader

          配置url-loader

          const?path?=?require('path')??
          const?MiniCssExtractPlugin?=?require('mini-css-extract-plugin')??
          const?HtmlWebpackPlugin?=?require('html-webpack-plugin')??
          const?{?CleanWebpackPlugin?}?=?require('clean-webpack-plugin')??
          module.exports?=?{??
          ??entry:?'./src/index.js',??
          ??output:?{??
          ????filename:?'main.js',??
          ????path:?path.resolve(__dirname,?'./dist')??
          ??},??
          ??mode:?'development',??
          ??module:?{??
          ????rules:?[??
          ??????{??
          ????????test:?/\.css$/,??
          ????????use:?[??
          ??????????MiniCssExtractPlugin.loader,??
          ??????????'css-loader',??
          ??????????'postcss-loader'??
          ????????]??
          ??????},??
          ??????{??
          ????????test:?/\.(png|jpe?g|gif)$/,??
          ????????use:?{??
          ??????????loader:?'url-loader',??
          ??????????options:?{??
          ????????????name:?'[name].[ext]',??
          ????????????limit:?1024?*?3??
          ??????????}??
          ????????}??
          ??????}??
          ????]??
          ??},??
          ??plugins:?[??
          ????new?MiniCssExtractPlugin({??
          ??????filename:?"css/[name].css",??
          ????}),??
          ????new?HtmlWebpackPlugin({??
          ??????template:?'./src/index.html'??
          ????}),??
          ????new?CleanWebpackPlugin()??
          ??]??
          }????
          • [ext]表示導(dǎo)入時(shí)是什么格式,導(dǎo)出時(shí)就是什么格式
          • limit表示圖片大小的閾值,超過閾值的圖片會被原封不動的放置到打包文件夾下(file-loader做的這件事情,在js中引入時(shí)會幫你生成一個(gè)地址,即打包后對應(yīng)的訪問地址),沒有超過會處理成base64放在bundle文件中

          在入口文件中引入圖片

          //?index.js??
          import?'./index.css'??
          import?mk85?from?'./assets/images/mk85.jpeg'??
          console.log(mk85)?//?mk85.jpeg??
          const?img?=?document.createElement('img')??
          img.src?=?mk85??
          const?BoxDiv?=?document.getElementsByClassName('box')??
          BoxDiv[0].appendChild(img)??
          ??

          運(yùn)行webpack命令看一下結(jié)果

          4eb1dfd6b73427463ad7ba79ad99d6ff.webp

          實(shí)現(xiàn)圖片在css文件中引入

          在css中引入圖片我們依舊使用url-loader,但需要對配置稍微進(jìn)行修改

          css代碼

          .box?{??
          ??width:?100px;??
          ??height:?100px;??
          ??/*?background-color:?yellowgreen;?*/??
          ??background-image:?url("./assets/images/mk85.jpeg");??
          ??display:?flex;??
          }????

          直接引用并打包,打包成功!打開html頁面,發(fā)現(xiàn)看不到圖片,因?yàn)榈刂凡粚?。打包后mk85圖片在dist文件夾下,而index.css的引用路徑依舊是mk85.jpeg,可index.css是在css文件夾下的,所以自然是無法引用到。

          那如何才能引用到呢?最簡單的方法就是加上/但這里有坑(其實(shí)也不是坑,這是一個(gè)關(guān)于/images、./images、image三者有什么不同的知識點(diǎn))。補(bǔ)充:create-react-app也是通過/ 實(shí)現(xiàn)引用統(tǒng)一的

          40f9874d99874e47bdbeb0df678e4c02.webp

          修改url-loader配置

          const?path?=?require('path')??
          const?MiniCssExtractPlugin?=?require('mini-css-extract-plugin')??
          const?HtmlWebpackPlugin?=?require('html-webpack-plugin')??
          const?{?CleanWebpackPlugin?}?=?require('clean-webpack-plugin')??
          ??
          module.exports?=?{??
          ??entry:?'./src/index.js',??
          ??output:?{??
          ????filename:?'main.js',??
          ????path:?path.resolve(__dirname,?'./dist')??
          ??},??
          ??mode:?'development',??
          ??module:?{??
          ????rules:?[??
          ??????{??
          ????????test:?/\.css$/,??
          ????????use:?[??
          ??????????MiniCssExtractPlugin.loader,??
          ??????????'css-loader',??
          ??????????'postcss-loader'??
          ????????]??
          ??????},??
          ??????{??
          ????????test:?/\.(png|jpe?g|gif)$/,??
          ????????use:?{??
          ??????????loader:?'url-loader',??
          ??????????options:?{??
          ????????????name:?'[name].[ext]',??
          ????????????limit:?1024?*?3,??
          ????????????outputPath:?"images/",??
          ????????????publicPath:?"/images",??
          ??????????}??
          ????????}??
          ??????}??
          ????]??
          ??},??
          ??plugins:?[??
          ????new?MiniCssExtractPlugin({??
          ??????filename:?"css/[name].css",??
          ????}),??
          ????new?HtmlWebpackPlugin({??
          ??????template:?'./src/index.html'??
          ????}),??
          ????new?CleanWebpackPlugin()??
          ??]??
          }????
          • outputPath表示輸出的到哪里(file-loader提供的)
          • name: images/[name].[ext]這樣寫和用outputPath設(shè)置效果一樣嗎?在配合publicPath字段時(shí)不一樣。所以當(dāng)你不需要配置publicPath字段時(shí),可以通過name設(shè)置輸出路徑(file-loader提供的)
          ?options:?{??
          ????name:?'[name].[ext]',??
          ???limit:?1024?*?3,??
          ???outputPath:?"images/",??
          ????publicPath:?"/images",??
          ?}??
          ?
          ?//?等價(jià)于??
          ?
          ?options:?{??
          ??name:?'images/[name].[ext]',??
          ??limit:?1024?*?3,??
          ??publicPath:?"/",??
          ?}????
          • publicPath表示資源引用的路徑

          運(yùn)行webpack命令看一下結(jié)果

          7892091d706d2e2b565d5a719c1e6d25.webp

          成功了!是我們想要的結(jié)果,不過問題又來了,當(dāng)你打開html頁面時(shí)發(fā)現(xiàn)并不能看到圖片正常顯示,這里就牽扯到關(guān)于/images、./imagesimage三者有什么不同的知識點(diǎn)

          簡單來說,如果我起了服務(wù),我的實(shí)際路徑就是“l(fā)ocalhost:8080/images/mk85.jpeg”,如果沒有起服務(wù)那就是“/images/mk85.jpeg”

          所以讓我們開啟一個(gè)服務(wù)吧!

          實(shí)現(xiàn)webpack本地服務(wù)

          安裝webpack-dev-server

          yarn?add?webpack-dev-server?-D????

          配置url-loader

          const?path?=?require('path')??
          const?MiniCssExtractPlugin?=?require('mini-css-extract-plugin')??
          const?HtmlWebpackPlugin?=?require('html-webpack-plugin')??
          const?{?CleanWebpackPlugin?}?=?require('clean-webpack-plugin')??
          ??
          module.exports?=?{??
          ??entry:?'./src/index.js',??
          ??output:?{??
          ????filename:?'main.js',??
          ????path:?path.resolve(__dirname,?'./dist')??
          ??},??
          ??mode:?'development',??
          ??module:?{??
          ????rules:?[??
          ??????{??
          ????????test:?/\.css$/,??
          ????????use:?[??
          ??????????MiniCssExtractPlugin.loader,??
          ??????????'css-loader',??
          ??????????'postcss-loader'??
          ????????]??
          ??????},??
          ??????{??
          ????????test:?/\.(png|jpe?g|gif)$/,??
          ????????use:?{??
          ??????????loader:?'url-loader',??
          ??????????options:?{??
          ????????????name:?'[name].[ext]',??
          ????????????limit:?1024?*?3,??
          ????????????outputPath:?"images/",??
          ????????????publicPath:?"/images",??
          ??????????}??
          ????????}??
          ??????}??
          ????]??
          ??},??
          ??devServer:?{??
          ????open:?true,??
          ????port:?8080,??
          ??},??
          ??plugins:?[??
          ????new?MiniCssExtractPlugin({??
          ??????filename:?"css/[name].css",??
          ????}),??
          ????new?HtmlWebpackPlugin({??
          ??????template:?'./src/index.html'??
          ????}),??
          ????new?CleanWebpackPlugin()??
          ??]??
          }????
          • 只需要加上devServer配置即可
          • open表示打開瀏覽器
          • port表示服務(wù)的端口號

          注意:這時(shí)就不是使用webpack命令來啟動項(xiàng)目了,需使用webpack-dev-server來啟動

          實(shí)現(xiàn)多頁面打包

          顧名思義,多頁面自然是有多個(gè)html頁面,每個(gè)html頁面都有自己的js文件,那么,有多少個(gè)入口就要有多少個(gè)出口

          我們首先要設(shè)置一下目錄形式,以適應(yīng)多頁面打包的形式(以下形式不是唯一的,但有助于大家的理解)

          ce139afe2e9ba627d1bfc6f55b231d3f.webp
          • 這里不需要src/index.js
          • 新建一個(gè)webpack.multiple.config.js
          • 新建src/pages/login/js/index.js
          • 新建src/pages/main/js/index.js

          安裝glob,用于處理文件

          yarn?add?glob?-D????

          配置webpack.multiple.config.js

          module.exports?=?{??
          ??entry:?{??
          ????login:?'./src/pages/login/js/index.js',??
          ????main:?'./src/pages/main/js/index.js'??
          ??},??
          ??output:?{??
          ????filename:?'[name].js',??
          ????path:?path.resolve(__dirname,?'./dist')??
          ??},??
          ??plugins:?[??
          ????new?HtmlWebpackPlugin({??
          ??????template:?'./src/index.html',??
          ??????filename:?'login.html',??
          ??????chunks:?['login']?//?chunks的名字對應(yīng)entry中的名字??
          ????}),??
          ????new?HtmlWebpackPlugin({??
          ??????template:?'./src/index.html',??
          ??????filename:?'main.html',??
          ??????chunks:?['main']??
          ????})??
          ??]??
          }????

          這樣就完成了!你可以使用webpack --config ./`webpack.multiple.config.js 命令運(yùn)行一下。結(jié)果會如你所愿的

          但是,這時(shí)你肯定會想難道我每寫一個(gè)頁面就重新配置一次嗎?這也太麻煩了,也不優(yōu)雅!那我們現(xiàn)在解決一下這個(gè)問題吧,直接上代碼

          //?我們寫一個(gè)方法自動做我們上面配置的事情??
          const?glob?=?require("glob")??
          ??
          const?setMpa?=?()?=>?{??
          ??const?entry?=?{}??
          ??const?htmlwebpackplugins?=?[]??
          ?//?通過glob庫拿到我們的入口文件數(shù)組??
          ??const?entryFiles?=?glob.sync(path.resolve(__dirname,?"./src/pages/*/*/index.js"))??
          ?//?console.log(entryFiles)??
          ??//?打印結(jié)果??
          ??//?[??
          ??//??'/Users/yzy/Desktop/learnSpace/learnWebpack/src/pages/login/js/index.js',??
          ??//??'/Users/yzy/Desktop/learnSpace/learnWebpack/src/pages/main/js/index.js'??
          ??//?]??
          ??entryFiles.forEach((item)?=>?{??
          ????const?entryFile?=?item??
          ????const?match?=?entryFile.match(/src\/pages\/(.*)\/js\/index\.js$/)??
          ????//?console.log(match)??
          ????//?打印結(jié)果??
          ????//?[??
          ????//???'src/pages/login/js/index.js',??
          ????//???'login',??
          ????//???index:?43,??
          ????//???input:?'/Users/yzy/Desktop/learnSpace/learnWebpack/src/pages/login/js/index.js',??
          ????//???groups:?undefined??
          ????//?]??
          ????const?pageName?=?match[1]??
          ????entry[pageName]?=?entryFile??
          ????htmlwebpackplugins.push(??
          ??????new?HtmlWebpackPlugin({??
          ????????template:?`./src/index.html`,??
          ????????filename:?`${pageName}.html`,??
          ????????chunks:?[pageName]??
          ??????})??
          ????)??
          ??})??
          ??
          ??return?{??
          ????entry,??
          ????htmlwebpackplugins,??
          ??}??
          }????

          有了這個(gè)方法以后,我們把它加到配置文件里

          const?path?=?require('path')??
          const?MiniCssExtractPlugin?=?require('mini-css-extract-plugin')??
          const?HtmlWebpackPlugin?=?require('html-webpack-plugin')??
          const?{?CleanWebpackPlugin?}?=?require('clean-webpack-plugin')??
          const?glob?=?require("glob")??
          ??
          const?setMpa?=?()?=>?{??
          ??const?entry?=?{}??
          ??const?htmlwebpackplugins?=?[]??
          ??const?entryFiles?=?glob.sync(path.resolve(__dirname,?"./src/pages/*/*/index.js"))??
          ??entryFiles.forEach((item)?=>?{??
          ????const?entryFile?=?item??
          ????const?match?=?entryFile.match(/src\/pages\/(.*)\/js\/index\.js$/)??
          ????const?pageName?=?match[1]??
          ????entry[pageName]?=?entryFile??
          ????htmlwebpackplugins.push(??
          ??????new?HtmlWebpackPlugin({??
          ????????template:?`./src/index.html`,??
          ????????filename:?`${pageName}.html`,??
          ????????chunks:?[pageName]??
          ??????})??
          ????)??
          ??})??
          ??
          ??return?{??
          ????entry,??
          ????htmlwebpackplugins,??
          ??}??
          }??
          const?{?entry,?htmlwebpackplugins?}?=?setMpa()??
          module.exports?=?{??
          ??entry,??
          ??output:?{??
          ????filename:?'[name].js',??
          ????path:?path.resolve(__dirname,?'./dist')??
          ??},??
          ??mode:?'development',??
          ??module:?{??
          ????rules:?[??
          ??????{??
          ????????test:?/\.css$/,??
          ????????use:?[??
          ??????????'style-loader',??
          ??????????'css-loader',??
          ??????????'postcss-loader'??
          ????????]??
          ??????},??
          ??????{??
          ????????test:?/\.(png|jpe?g|gif)$/,??
          ????????use:?{??
          ??????????loader:?'url-loader',??
          ??????????options:?{??
          ????????????name:?'[name].[ext]',??
          ????????????limit:?1024?*?3,??
          ????????????outputPath:?"images/",??
          ????????????publicPath:?"/images",??
          ??????????}??
          ????????}??
          ??????}??
          ????]??
          ??},??
          ??devServer:?{??
          ????open:?true,??
          ????port:?8080,??
          ????hot:?true??
          ??},??
          ??plugins:?[??
          ????new?MiniCssExtractPlugin({??
          ??????filename:?"css/[name].css",??
          ????}),??
          ????new?CleanWebpackPlugin(),??
          ????...htmlwebpackplugins??
          ??]??
          }????

          我們再使用webpack --config ./`webpack.multiple.config.js 命令運(yùn)行一下,成功!

          小結(jié)

          到這里就算是完成了一個(gè)簡單的webpack項(xiàng)目配置,看到這里先不要著急往下看,思考一下是否真的了解了loader和plugin,如果讓你寫一個(gè)loader和plugin,你有思路嗎

          我想不出意外的話,你應(yīng)該是已經(jīng)有了思路。如果沒有也不用擔(dān)心,看看下面的內(nèi)容

          實(shí)現(xiàn)一個(gè)loader

          先上鏈接,官網(wǎng)編寫loader文檔[12]

          首先loader是一個(gè)函數(shù),注意這里不能是箭頭函數(shù)

          編寫一個(gè)替換字符串的loader

          //?replaceLoader.js??
          module.exports?=?function?(soure)?{??
          ??console.log(soure,?this)?//?這里可以自己打印看一下信息,內(nèi)容太長我就不放進(jìn)來了??
          ?return?source.replace('hello?webpack',?"你好呀,webpack!")??
          }????
          • loader是一個(gè)函數(shù)
          • 不能使用箭頭函數(shù),因?yàn)橐玫缴舷挛牡膖his
          • soure接收到的是待處理的文件源碼
          • return處理后的文件源碼,也是下一個(gè)loader接收到的文件源碼

          使用loader

          {??
          ??test:?/\.js$/,??
          ??use:?path.resolve(__dirname,?'./loader/replaceLoader.js')??
          }????

          運(yùn)行webpack命令看一下結(jié)果

          01006c03d3ebb583d1bc73298b510133.webp

          成功!是不是發(fā)現(xiàn)原來自定義loader這么簡單,感興趣可以自己嘗試寫一下css、png等其他文件的loader

          實(shí)現(xiàn)一個(gè)plugin

          線上鏈接,官網(wǎng)編寫plugin文檔[13]

          同樣簡單,我們已經(jīng)用了很多次plugin了,發(fā)現(xiàn)是不是都需要new一下。很顯然,自定義loader是一個(gè)構(gòu)造函數(shù)。

          我們看一下格式:

          class?PluginName?{??
          ?constructor?(options)?{??
          ?}??
          ?apply(compiler)?{??
          ??...??
          ?}??
          }????
          • 這里一定要寫apply方法,webpack會通過apply方法啟動插件
          • PluginName可以寫成普通function,apply必須掛載到原型對象上(PluginName.prototype
          • class類中的apply不能寫成箭頭函數(shù)
          • webpack的compiler鉤子[14],查看鉤子決定你的插件要在哪一步做什么

          編寫一個(gè)假的html-webpack-plugin,輸出一個(gè)fake.html文件

          class?HtmlPlugin?{??
          ?constructor?(options)?{??
          ?}??
          ?apply(compiler)?{??
          ??compiler.hooks.emit.tap('HtmlPlugin',?(compolation)?=>?{??
          ??????const?content?=?'fake?html'??
          ??????compolation.assets['fake.html']?=?{??
          ????????source:?function?()?{??
          ??????????return?content??
          ????????},??
          ????????size:?function?()?{??
          ??????????return?content.length??
          ????????}??
          ??????}??
          ????})??
          ?}??
          }??
          module.exports?=?HtmlPlugin????

          使用這個(gè)plugin

          plugins:?[??
          ??new?HtmlPlugin()??
          ]????

          運(yùn)行webpack命令看一下結(jié)果

          3a3b211499ff3f41248e71037a2a9a1f.webp

          成功!你也可以試著完善一下這個(gè)插件,加上配置,加上引入資源文件等

          指紋策略

          關(guān)于瀏覽器緩存

          • 現(xiàn)代瀏覽器都會有緩存機(jī)制

          • 當(dāng)我們第一次訪問A網(wǎng)站時(shí),這時(shí)加載了y.js的文件進(jìn)行了緩存

          • 當(dāng)我們第二次訪問A網(wǎng)站時(shí),瀏覽器發(fā)現(xiàn)緩存中已經(jīng)有y.js了

            • 緩存中有y.js那就用緩存的文件
            • 優(yōu)點(diǎn):減少了資源的請求
            • 缺點(diǎn):當(dāng)y.js的內(nèi)容更新了,若不通過強(qiáng)制刷新瀏覽器的話則無法獲取最新的y.js內(nèi)容
          • 我們加上標(biāo)識符就可以解決這個(gè)問題了

            • 第一次訪問時(shí)加載了y.123.js
            • 第二次訪問發(fā)現(xiàn)有緩存就用緩存中的y.123.js
            • 這時(shí)服務(wù)器中的y文件內(nèi)容改變了,同時(shí)也修改了名字為y.111.js
            • 第三次訪問發(fā)現(xiàn)沒有y.111.js文件,正確加載最新y.111.js

          上訴都是比較簡單解釋,具體細(xì)節(jié)你可以不用知道,明白這個(gè)緩存機(jī)制的緩存方式即可

          webpack中使用指紋策略

          使用:

          filename:?'[name].[hash].[ext]',????
          • hash:以項(xiàng)目為單位,項(xiàng)目內(nèi)容改變了,則會生成新的hash,內(nèi)容不變則hash不變

            • 整個(gè)工程任何一個(gè)需要被打包的文件發(fā)生了改變,打包結(jié)果中的所有文件的hash值都會改變
          • chunkhash:以chunk為單位,當(dāng)一個(gè)文件內(nèi)容改變,則整個(gè)chunk組的模塊hash都會改變

            • 假設(shè)打包出口有a.123.js和c.123.js
            • a文件中引入了b文件
            • 修改了b文件的內(nèi)容
            • 重新的打包結(jié)果為a.111.js和c.123.js
            • a的hash值會被影響,但是c的hash值不受影響
          • contenthash:以自身內(nèi)容為單位,依賴不算

            • 假設(shè)打包出口有a.123js和b.123.css
            • a文件引入了b文件
            • 修改了b文件的內(nèi)容
            • 重新打包結(jié)果為a.123.js和b.111.css
            • a的hash值不受影響
          熱模塊替換

          你一定使用過這個(gè)功能,只是你不知道罷了!

          場景:

          • 啟動項(xiàng)目本地服務(wù)
          • 修改了一個(gè).css文件的內(nèi)容
          • 瀏覽器沒有刷新,但是修改的內(nèi)容還是生效了

          這就是熱模塊替換,提示:無論是css還是js都可以做熱模塊替換,但是個(gè)人建議只做css的熱模塊替換即可。因?yàn)閖s的熱模塊替換需要寫代碼進(jìn)行替換,除非特定情況下,否則js的熱模塊替換用處不大。

          我們來做一個(gè)css的熱模塊替換吧

          注:熱模塊替換不支持抽取出的css文件,只能放在style中,所以需要style-loader

          配置webpack.config.js

          const?path?=?require('path')??
          const?MiniCssExtractPlugin?=?require('mini-css-extract-plugin')??
          const?HtmlWebpackPlugin?=?require('html-webpack-plugin')??
          const?{?CleanWebpackPlugin?}?=?require('clean-webpack-plugin')??
          const?HtmlPlugin?=?require('./plugin/htmlPlugin')??
          const?Webpack?=?require('webpack')??
          ??
          module.exports?=?{??
          ??entry:?'./src/index.js',??
          ??output:?{??
          ????filename:?'main.js',??
          ????path:?path.resolve(__dirname,?'./dist')??
          ??},??
          ??mode:?'development',??
          ??module:?{??
          ????rules:?[??
          ??????{??
          ????????test:?/\.js$/,??
          ????????use:?path.resolve(__dirname,?'./loader/replaceLoader.js')??
          ??????},??
          ??????{??
          ????????test:?/\.css$/,??
          ????????use:?[??
          ??????????//?MiniCssExtractPlugin.loader,??
          ??????????'style-loader',??
          ??????????'css-loader',??
          ??????????'postcss-loader'??
          ????????]??
          ??????},??
          ??????{??
          ????????test:?/\.(png|jpe?g|gif)$/,??
          ????????use:?{??
          ??????????loader:?'url-loader',??
          ??????????options:?{??
          ????????????name:?'[name].[ext]',??
          ????????????limit:?1024?*?3,??
          ????????????outputPath:?"images/",??
          ????????????publicPath:?"/images",??
          ??????????}??
          ????????}??
          ??????}??
          ????]??
          ??},??
          ??devServer:?{??
          ????open:?true,??
          ????port:?8080,??
          ????hot:?true??
          ??},??
          ??plugins:?[??
          ????new?MiniCssExtractPlugin({??
          ??????filename:?"css/[name].css",??
          ????}),??
          ????new?HtmlWebpackPlugin({??
          ??????template:?'./src/index.html'??
          ????}),??
          ????new?CleanWebpackPlugin(),??
          ????new?HtmlPlugin(),??
          ????new?Webpack.HotModuleReplacementPlugin()??
          ??]??
          }????

          思考了一下,還是附了一份完整的配置文件(有點(diǎn)擔(dān)心這樣太占頁面位置了)

          • 首先,將之前的MiniCssExtractPlugin.loader替換回style-loader
          • 給devServer中加上hot: true
          • 引入webpack: const Webpack = require('webpack')
          • 在plugin中添加:new Webpack.HotModuleReplacementPlugin()

          運(yùn)行webpack-dev-server命令看看效果吧!

          webpack5都更新了什么

          話不多說,直接上鏈接,webpack5更新的內(nèi)容[15]

          提示:當(dāng)你使用webpack4的時(shí)候,無論是裝plugin(插件)還是loader都盡量看看該插件現(xiàn)在都有什么版本,如果發(fā)現(xiàn)版本從4.x一下子跳到了5.x,那么一定要去安裝4.x的版本,否則在打包的時(shí)候會發(fā)生未知的錯(cuò)誤

          參考資料

          [1]

          https://github.com/postcss/autoprefixer

          [2]

          https://github.com/postcss/postcss

          [3]

          https://github.com/postcss/postcss#plugins

          [4]

          https://www.babeljs.cn/docs/plugins

          [5]

          https://www.babeljs.cn/docs/presets

          [6]

          https://github.com/browserslist/browserslist

          [7]

          https://webpack.js.org/configuration/mode/

          [8]

          https://webpack.docschina.org/plugins/mini-css-extract-plugin/

          [9]

          https://webpack.docschina.org/plugins/html-webpack-plugin/

          [10]

          https://github.com/jantimon/html-webpack-plugin#options

          [11]

          https://www.npmjs.com/package/clean-webpack-plugin

          [12]

          https://webpack.docschina.org/contribute/writing-a-loader/

          [13]

          https://webpack.docschina.org/contribute/writing-a-plugin/

          [14]

          https://webpack.docschina.org/api/compiler-hooks/

          [15]

          https://zhuanlan.zhihu.com/p/268925969

          作者:KDDA_

          https://juejin.cn/post/6953042611963691021

          祝 :2022 年暴富!萬事如意!

          點(diǎn)贊和在看就是最大的支持,ada16f89b1f84b5f20218aa451c20c60.webp比心??ada16f89b1f84b5f20218aa451c20c60.webp

          瀏覽 58
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <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>
                  我要看日本一级黄色片 | 操碰100| 免费看操逼| 欧美性爱亚洲日韩 | 久久天天躁 |