從0到1教你學習并配置webpack

抓住2019年的尾巴,迎接2020年的到來~

給自己的2019年畫上一個完美的句號。

引言

webpack 對于現在的前端開發的你來說,不算陌生,你或許沒有真正去了解過它是如何使用的,但你的項目中確實使用過它,因為你項目的打包編譯都跟他息息相關~

前陣子剛好在研究webpack以及其源碼相關的知識,如果你跟我一樣,好奇webpack又是怎么工作的?那些奇奇怪怪的配置都是什么東西?分別代表什么意思?

那你不妨花幾分鐘閱讀一下,跟我一起學習回顧一下如何從0到1去了解webpack的知識, 配置你項目需要的webpack~

pass:本文以 webpack4 為例~

什么是webpack?

什么是 webpack

官方文檔 是這么說:

webpack 是一個現代 JavaScript 應用程序的靜態模塊打包器(module bundler)。當 webpack 處理應用程序時,它會遞歸地構建一個依賴關系圖(dependency graph),其中包含應用程序需要的每個模塊,然后將所有這些模塊打包成一個或多個 bundle

其實,它就是一個模塊化打包工具,它所做的事情就是分析你的項目結構,找到JavaScript模塊并對其進行代碼轉換(scss 轉換為cssTypescript 轉換為 Javscript),文件優化(壓縮JavaScriptCSSHTML、圖片等),模塊合并 (把模塊分類合并成一個文件)等一系列的操作,最終打包為合適的格式在讓你的項目可以在瀏覽器中運行~

盜用官網的一張圖,其主要工作原理就如下圖所示~

核心概念

在真正上手 webpack 之前,我們需要對其幾個 核心概念 有所了解

  • Entry:入口路徑,webpack執行構建的第一步的輸入文件。

  • Module:模塊,在 webpack 里一切皆模塊,一個模塊對應著一個文件,webpack 會從配置的 Entry 開始遞歸找出所有依賴的模塊。

  • Chunk:代碼塊,一個 Chunk 由多個模塊組合而成,用于代碼合并與分割。

  • Loader:模塊轉換器,用于把模塊原內容按照需求轉換成新內容,例如scsscss的轉換等,構建模塊的第一步就是使用loader來加載并處理模塊內容

  • Plugin:擴展插件,webpack 的重要組成部分,其 webpack 源碼的很多核心功能也都是插件實現的,由于webpack提供了在不同的生命周期內提供了很多不同的hooks鉤子函數,插件的工作原理就是在 webpack 構建流程中的不同的(hooks)時機注入擴展邏輯來改變構建結果或做個性化操作。

  • Output:輸出結果,在 webpack 經過一系列處理后最終代碼后輸出配置。

整個流程串起來大概就是:

webpack啟動后會從Entry里配置的Module開始遞歸解析 Entry 依賴的所有 Module。 每找到一個 Module,就會根據配置的Loader去找出對應的轉換規則,對 Module 進行轉換后,再解析出當前 Module 依賴的 Module

這些模塊會以 Entry 為單位進行分組,一個 Entry 和其所有依賴的 Module 被分到一個組也就是一個Chunk。最后 webpack 會把所有 Chunk 轉換成文件輸出,在這整個流程中 webpack 會在不同的生命周期內執行配置的 Plugin 里定義的邏輯。

了解了上面的一些概念和流程之后,接下來,我們一步步來配置,打包我們的項目~

初始化項目

創建文件夾

首先,我們創建一個你喜歡的文件夾,并通過 npm init -y 來初始化項目配置,并在其目錄下創建一個我們源代碼的目錄src和一個打包后的文件輸入目錄dist

創建入口文件 index.js

然后我們在 src 目錄下創建一個 index.js 文件,作為我們的打包入口文件,并寫上我們熟悉的 console.log('hello world'); 作為打包內容。

安裝webpack

webpack4 之后將 webpackcli 分成了兩個包,我們需要通過 npm install webpack webpack-cli -D 安裝我們所需的 webpack 依賴。

ok~ 準備就緒!

遺憾的是,你還是不能直接進行打包,因為我們的 webpack 是在項目下安裝的,所以不能直接運行,想要正確運行webpakc我們可以有下面2種方式:

  • 使用 npx 命令,可以直接運行 node_modules/.bin 目錄下的命令
  • 通過配置 package.json 中的 scripts 腳本命令進行執行

為了貼近我們的項目,這里我們選擇第二種方式

配置package.json腳本

我們打開package.json文件,并在 scripts 中配置下面的代碼:

    "dev" : "webpack --mode development",
    "build" : "webpack --mode production",

dev 表示開發模式,build 是生產模式,不同在于 dev 會有很多方便我們開發調試的功能,比如代碼不壓縮混淆,有開發服務器之類的,我們學習階段采用 dev 即可~

創建配置文件

這時候,我們已經可以通過 npm run dev 命令打包我們的代碼,并在dist目錄下看到我們打包后的 main.js 文件了~

你可能很詫異的蹦出一句:

因為到此,你發現自己什么都還沒配置,咋就可以打包了!!

這是因為 webapck4 為了簡化我們開發人員繁瑣的配置工作,在內部寫好了一套配置,驚不驚喜,意不意外!!

那我這肯定不能答應了,不然不就打我臉了么!

要想加載自己的配置,我們需要在我們的項目根目錄下創建 webpack.config.js 文件,并創建我們的基礎配置。

//path
const path = require('path');

//配置信息
module.exports = {
    //入口文件
    entry : './src/index.js' ,
    //出口文件
    output : {
        //打包后路徑,只能寫絕對路徑
        path : path.resolve(__dirname,'dist'),
        //打包后文件名
        filename : '[name].[hash].js'
    },
    //模塊轉換規則
    module : {
    
    },
    //插件
    plugins : [
    
    ],
    //開發服務器
    devServer : {
    
    }
}

我們注意到 output 中的 filename 中有一個 [name][hash],其中nameentry 的名字,默認是 mainhash 是打包根據內容后計算出的一個 hash值,保證文件的唯一性,可以通過[hash:8] 表示取其前8位。

現在運行 npm run devdist 目錄下就會打包出類似 main.47bfc309d4ba9b75d346.js 的文件。

這里,我們為了方便,先將其改成 main.js

創建index.html文件

為了方便我們在瀏覽器測試,我們在我們的 dist 目錄創建一個 index.html ,并引入我們編譯好的main.js文件,如下:

//index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>webpack</title>
</head>
<body>
<div id="app">webpack</div>
<script src="main.js"></script>
</body>
</html>

我們在 index.js 文件下加上這么一句話:

document.querySelector('#app').style.color='red';

測試一下打包后的文件好不好使。

運行 npm run dev,打開我們的 index.html 預覽,不出意外的話,結果應該和我一樣,頁面的 webpack 文字變紅,控制臺輸出 hello world

至此,我們才將我們的項目基礎配置搞定~

加載css

如果我們現在想加入 css 文件,優化我的樣式,首先在 src 目錄下創建 stylesheets 目錄,并添加 index.css 文件,我們就先以 body { background : #f2f2f2; } 為例,之后在 index.js 中通過 import './stylesheets/index.css' 的方式導入樣式文件。

如果現在我們直接進行打包肯定會報錯,因為 css 文件并不是 js 模塊,webpack 在打包的時候沒法直接處理,需要借助轉換工具,這轉換工具就是 Loader

  • 什么是 Loader

Loader 就是文件轉換器,通過使用不同的Loaderwebpack就可以把不同的文件都轉成js文件,比如CSSES6/7JSX等,它通常有下面幾個配置項:

  • test:匹配處理文件的擴展名的正則表達式
  • useloader名稱,就是你要使用模塊的名稱
  • include/exclude:手動指定必須處理的文件夾或屏蔽不需要處理的文件夾
  • query:為loaders提供額外的設置選項

接下來,我們來使用 style-loadercss-loader 來處理我們的 css 文件。

執行 npm install style-loader css-loader -D 進行安裝 loader

webpack.config.js 中的module下面添加解析規則:

module : {
    rules : [{
        test : /\.css$/,
        use : ['style-loader','css-loader']
    }]
},

通常來說,loader有下面三種書寫方式,上面是通過 use 方式,還有兩種方式分別是 直接使用 loader 和使用 use + loader

//直接使用loader

module: {
    rules: [{
        test: /\.css/,
        loader:['style-loader','css-loader']
    }]
}
//use + loader 的方式

module: {
    rules: [{
        test: /\.css/,
        include: path.resolve(__dirname,'src'),
        exclude: /node_modules/,
        use: [{
            loader: 'style-loader',
            options: {
                insert:'top'
            }
        },'css-loader']
    }]
}

要注意的是配置多個 loader有順序 的,webpack 會安裝配置的 loader 順序 從右向左 執行的,配置的時候要格外注意!

拿我們上面的 style-loadercss-loader 來說,兩個loader配置的順序不可調換,因為 css-loader是解析處理css里的url路徑,并將css文件轉換成一個模塊,style-loader是 將css文件變成style標簽插入到head中的。

現在我們 npm run dev 試試,打包沒有報錯,預覽 index.html 也成功生效,很贊!

配置開發服務器

到此你有沒有發現,我們在平時的開發過程中,怎么沒有遇到說讓我每次通過預覽dist下的 index.html來看我們打包效果的,這是由于我們平時的開發中會在自己本地起一個服務器,來幫我們做這件事。

現在,我們也來試試~

  • 通過 npm i webpack-dev-server –D 安裝我們的開發服務器依賴
  • 修改我們的啟動腳本,將原來的 package.json 中的 dev 腳本修改為 webpack-dev-server --open ,其中 --open 是自動打開瀏覽器的意思

此時,直接運行 npm run dev 是看不到我們預期的效果的,因為我們還沒有對我們的服務器進行配置。

我們在 webpack.config.jsdevServer 下添加如下配置:

devServer : {
    contentBase : path.resolve(__dirname,'dist'),
    host : 'localhost' ,
    port : 8000 ,
    compress : true
}
  • contentBase 配置開發服務運行時的文件根目錄,也就是靜態資源訪問地址
  • host 開發服務器監聽的主機地址
  • port 開發服務器監聽的端口,默認是 8080
  • compress 開發服務器是否啟動gzip等壓縮

ok,運行 npm run dev ,是不是效果非常棒!

要注意的是,webpack dev server 產生的打包文件是在 內存中!,是 內存中!,硬盤是訪問不到的,怎么驗證這一點呢?

很簡單,你可以刪除掉你dist目錄下的 main.js ,重新運行 npm run dev ,你可以看到 dist 目錄下并沒有 main.js,但你訪問 localhost:8000 確實能正確訪問,并且訪問 http://localhost:8000/main.js 也能看到打包后的源碼,證明它產生的打包文件確實是在你的 內存中

注意,我們這里打包出來的只有一個 main.js 文件和一個index.css文件,index.html 文件是我們手動添加進去的,不是打包產生的,如果刪掉 index.html 是無法正確訪問頁面的,內存里可沒有 index.html 文件。

我們可以在終端看到以下這些內容:

這些都是我們在啟動開發服務器的時候 webpack 給我們的頁面注入的 websocket 連接,你可以在你的頁面調試器的 network 中的 ws 里看到,

其重要作用就是,監控你文件的變化,可以幫助你重新刷新頁面,讓你看到更改后的效果,你可以修改一下 index.js 文件試試~

自動生產HTML文件

我們之前是在 dist 目錄下寫好了 index.html 文件,并在里面通過 script 標簽引入我們打包后的內容,即 main.js ~

還記得我們之前打包后的 filename 中可以加入一個 hash 值也區別不同的文件,如果 hash 值發生變化了,我們的 index.html 豈不是找不到資源了?所以我們希望自動能產出HTML文件,并在里面引入產出后的資源,這樣就不必為上面的問題擔心了。

我們刪除掉 dist 目錄下的 index.html 文件,并在 src 目錄下創建一個 index.html 文件,我們稱它為模板,以它為模板產生 html 文件。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
    <title>webpack</title>
</head>
<body>
    <div id="app">webpack</div>
</body>
</html>

這時,我們需要接觸到第一個插件 html-webpack-plugin!

之前也說了,插件在 webpack 中有很重要的作用,在 webpack 的構建流程中,plugin 用于處理更多其他的一些構建任務,模塊代碼轉換的工作由 loader 來處理,除此之外的其他任何工作都可以交由 plugin 來完成。

  • 首先我們需要通過 npm install html-webpack-plugin -D 去安裝它。
  • 然后在 webpack.config.jsplugins 下去配置它(需要先通過 require 引入)
//自動產出HTML模版
new HtmlWebpackPlugin({
    template: './src/index.html',
    filename: 'index.html',
    hash: true,
    minify: {
        removeAttributeQuotes: true,
        removeComments: true 
    }
})

其中 template 是指定模板文件,filename 是指定產出后的文件名,hash 是為了避免緩存,可以在產出的資源后面添加hash值,minify 是 壓縮相關的配置,minify.removeAttributeQuotes 是為了去掉屬性的雙引號,minify.removeComments 是為了壓縮文件,刪除模板中的注釋。

此時,我們運行 npm run dev 訪問 localhost:8000 發現已經可以正常訪問了,但是 dist 目錄下卻沒有任何東西,因為我們之前提到了,開發服務器打包的文件是寫入內存中的,不是硬盤里。

為了方便我們看效果,我們在 package.json 中的 scripts 中在增加一行 "dev-build": "webpack --mode development" 用來打包我們開發環境的代碼。

運行 npm run dev-build 腳本,完成之后可以發現 dist 目錄已經打包出來了 index.html 文件 和 main.[hash].js 文件,打開 index.html 文件可以發現標簽的雙引號已經沒去掉了,并且引入的腳本也自動加上了 ?[hash] 值。

<!DOCTYPE html>
<html lang=en>
<head>
    <meta charset=UTF-8>
    <meta name=viewport content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
    <title>Title</title>
</head>
<body>
    <div id=app>webpack</div>
<script type=text/javascript src=main.e6570abab6c2814d1608.js?e6570abab6c2814d1608></script></body>
</html>

預覽 index.html 文件,一切也都正常。

passwebpack4以后,如果你看到終端輸入有下面這么怪異的一行,

而正巧你又是一個 強迫癥患者,在 webpack.config.js 中添加 stats: { children: false } 即可。

支持圖片

前端項目中肯定少不了圖片資源,如果我們直接在 css 或者 js 文件中引入圖片資源去打包,那么肯定是通不過了,因為 webpack 無法識別圖片資源,因為圖片也不是一個有效的模塊。

此時,我們需要引入這個兩個 loader 去解決它, file-loader url-loaderfile-loader 解決CSS等文件中的引入圖片路徑問題,url-loader 當圖片小于limit的時候會把圖片base64編碼,大于limit參數的時候還是使用file-loader 進行拷貝

  • 通過 npm install file-loader url-loader -D 下載依賴
  • src目錄下創建一個 images 文件夾,存放幾張你喜歡的圖片
  • index.jsindex.css 中引入圖片,并將其插入到頁面中去(我這里以本地的 avatar.jpgscene.jpg 為例)
//index.js
import Avatar from './images/avatar.jpg'

let img = new Image();

img.src = Avatar;

document.body.appendChild(img);
//index.css

body{
    background-color: #f2f2f2;
    background-image: url("../images/scene.jpg");
    background-repeat: no-repeat;
}
  • webpack.config.js中的module下面添加如下配置
{
    test:/\.(png|jpg|gif|svg|bmp)$/,
    use:{
        loader: 'url-loader',
        options: {
            limit: 10 * 1024,
            outputPath: 'images/'
        }
    }
}

options 中的 limit 就是圖片的限制,這里我指定的是 10kb ,小于 10kb 的圖片會以 base64 編碼輸出,outputPath 指定了拷貝文件輸出目錄,默認是dist目錄下。

現在我們 npm run dev-build 走一波~

也不報錯,運行 index.html 文件,也很正常!

編譯less 和 sass

現在開發過程中,為了簡化我們書寫 css 的過程,我們一般項目中引入了 lesssass 這樣的預加載器~

同樣的你不處理之前 webpack 是不認識 lesssass 文件的,畢竟它不是一個 js 模塊,我們通過需要借助 less-loadersass-loader 來處理這些文件~

  • 通過運行 npm install less less-loader -D npm install node-sass sass-loader -D 分別安裝 loader
  • webpack.config.js中添加loader解析規則
{
    test: /\.less/,
    use: ['style-loader', 'css-loader', 'less-loader']
}, {
    test: /\.scss/,
    use: ['style-loader', 'css-loader', 'sass-loader']
}

這樣,你就可以放心在你的項目里引入 css 預處理了~

分離css

因為CSS的下載和js可以并行,當一個HTML文件很大的時候,那么頁面加載肯定會非常慢,那么我們希望可以把CSS單獨提取出來加載,為每個包含 CSSJS 文件創建一個 CSS 文件,按需加載。

我們需要 mini-css-extract-plugin 這么一個插件

  • 通過 npm install mini-css-extract-plugin -D 安裝模塊依賴
  • webpack.config.jsplugins 下去配置一下
new MiniCssExtractPlugin({
    filename: 'css/[name].[hash].css',
    chunkFilename: "css/[id].css"
})

除此之外,我們的還需要做一個操作就是將我們之前處理cssstyle-loader 改寫成下面這種形式:

{
    test: /\.css$/,
    use: [{
        loader: MiniCssExtractPlugin.loader
    }, 'css-loader']
},{
    test: /\.less/,
    use: [{
        loader: MiniCssExtractPlugin.loader
    }, 'css-loader', 'less-loader']
}, {
    test: /\.scss/,
    use: [{
        loader: MiniCssExtractPlugin.loader
    }, 'css-loader', 'sass-loader']
}

趁熱打鐵,趕緊來試試,npm run dev-build 進行打包~

預覽 index.html 頁面,打開控制臺network可以發現下載文件的時候多出了一個 main.css 文件,并且我們 htmlhead 頭,已經換成了 link 方式,并且你的 dist 目錄下會多出一個 css 的文件夾,里面存放打包后的 css 文件。

tips: 如果你在外部的css 文件中文件中引入圖片,而圖片放在了images目錄下,那么打包上線后的圖片會出現 404 的情況,你可以查看打包后的 css 文件,就可以反向是路徑的問題,需要配置一下 publicPath 即可~

{
    loader: MiniCssExtractPlugin.loader,
    options: {
        publicPath: '/'
    }
}

注意,這個一般是在 服務器 上會出現,本地打包后沒有起服務也是看不到的。

處理CSS3屬性前綴

我們在書寫 css 的時候,為了瀏覽器的兼容性,有時候我們必須加入-webkit-ms-o-moz這些瀏覽器前綴,但我們又不想去書寫這些繁瑣的東西,這時候可以交給我們 postcss 來處理~

postcss的主要功能只有兩個:

  • 第一個就是前面提到的把 CSS 解析成 JavaScript 可以操作的 抽象語法樹結構(Abstract Syntax Tree,AST)
  • 第二個就是調用插件來處理 AST 并得到結果

我們首先通過 npm install postcss-loader autoprefixer -D 來安裝依賴

想要這個 postcss 正常工作,我們需要配置兩個東西

  • 在根目錄下創建 postcss.config.js 配置文件,表示使用 autoprefixer 來進行補全
module.exports={
    plugins:[require('autoprefixer')]
}
  • webpack.config.js 中修改并添加對css處理的 loader
{
    test: /\.css$/,
    use: [{
        loader: MiniCssExtractPlugin.loader
    }, 'css-loader', 'postcss-loader'],
    include: path.join(__dirname, './src'),
    exclude: /node_modules/
}

這里我在我的 index.css 中添加了如下測試代碼:

//index.css
::placeholder {
    color: orange;
}

并在我的 index.js 中創建了一個 input 控件:

//index.js

let input = document.createElement('input');
document.body.appendChild(input);

運行 npm run dev-build 打包,預覽 index.html ,打開調試工具的的 sources板塊,查看 main.css , 發現對應的前綴已添加,并且我頁面的 input 已經變成了 orange~

轉義ES6/ES7

雖然 es6es7 的代碼我們已經或多或少都在項目中,但是大部分瀏覽器對于 es6es7 代碼的支持度并不高,很大部分的瀏覽器還是只能解析 es5 的代碼,為了讓我們能正常使用 es6es7的代碼,我們需要借助 webpack 對其進行轉義,轉成 es5 代碼。

我們需要借助 babel 這個工具,它是一個編譯JavaScript的平臺,可以把ES6/ES7的代碼轉義為ES5代碼。

  • 通過 npm install babel-loader @babel/core @babel/preset-env -D 安裝依賴
  • webpack.config.js 中添加 babel-loader ,因為 babel-loader只是告訴了 webpack 怎么處理 ES6ES7 代碼,但它并不會將 ES6ES7 代碼翻譯成向后兼容版本的代碼,因此需要指定一個 preset,它包含了代碼轉換的規則
{
    test: /\.js$/,
    loader : 'babel-loader' ,
    exclude:'/node_modules/'
}
  • 在我們的項目根目錄創建一個 .babelrc 的文件來配置,用來配置我們的 babel 相關
{
  "presets": [
    [
      "@babel/preset-env",
      {
        "targets": {
          "browsers": [
            "> 1%",
            "last 2 versions"
          ]
        },
        "debug":true //調試使用
      }
    ]
  ]
}
  • 我們在 index.js 文件中添加以下代碼測試一下,并打包測試一下:
const test = (n)=> {
    return new Promise(function (resolve) {
        setTimeout(()=>{
            resolve([1,2,3,4].map(v=>v * v ))
        },n*1000)
    }).then(res=>{
        console.log(res);
    })
}

console.log(test)

查看打包后的文件,發現轉換的不夠徹底,只能針對語法進行了轉換,對于 Promisemap 這些高級用法并沒有被轉換,這肯定是不行的,我們還要想辦法把這些新的特性,兼容到低版本的瀏覽器里。

我們還需要 babel 提供的另一個工具—— polyfill

  • npm install @babel/polyfill -D 安裝它
  • 在我們的入口文件 index.js 最頂部添加 import '@babel/polyfill'
  • 運行 npm run dev-build 編譯打包,雖然控制臺好想沒啥變化,但是我們的打包的文件 main.js 發生了很大變化,很明顯的一點,體積大了好幾十倍

這是由于為了兼容低版本瀏覽器,polyfill 里面添加了很多輔助代碼來幫助實現比如 Promisemap 這些新特性,默認情況下會被添加到每一個需要它的文件中,并且會全局注入,造成全局污染,如果我們在開發框架之類的,可能會發生沖突。

我們加了 debug 可以在終端看到,確實是加入了不少插件:

為了解決這個問題,我們引入 @babel/runtime 這個模塊,來避免重復導入的問題
如果是寫第三方庫或者框架

  • 運行 npm install @babel/runtime @babel/plugin-transform-runtime -D安裝模塊依賴
  • 配置@babel/runtime,并修改一下 preset-env的配置,加上 useBuiltIns: 'usage' ,表示會根據業務需求自動轉換需要轉換的新語法
{
  "presets": [
    [
      "@babel/preset-env",
      {
        "useBuiltIns": "usage",
        "targets": {
          "browsers": [
            "> 1%",
            "last 2 versions"
          ]
        },
        "debug":true //調試使用
      }
    ]
  ],
  "plugins": [
    [
      "@babel/plugin-transform-runtime",
      {
        "corejs": false,
        "helpers": true,
        "regenerator": true,
        "useESModules": true
      }
    ]
  ]
}
  • 配置完成,ok,我們再來運行 npm run dev-build 打包一次試試

終端日志可以看到注入的輔助代碼大幅度較少,文件的大小也大幅度減少,贊!

拷貝靜態文件

我們有些項目中的文件,不是 js ,也不是 css , 圖片之類的,比如 README.md這些靜態資源,我也希望能打包到我的項目里,怎么辦呢?

其實就是文件的拷貝操作,我們只需要將這些文件拷貝到目標目錄下即可,我們可以利用 copy-webpack-plugin 這個插件

  • 運行 npm run copy-webpack-plugin -D 安裝插件
  • 在項目目錄下創建一個 static/README.md 的測試文件
  • 修改 webpack.config.js , 將插件添加到配置里去
new CopyWebpackPlugin({
    from: path.resolve(__dirname,'src/static'),
    to:path.resolve(__dirname,'dist/static') 
})

from 是靜態資源目錄源地址,to是要拷貝文件的目標地址,so easy~

npm run dev-build 打包運行!

可以發現我們的 dist 目錄已經將 src/static 的文件拷貝到了 dist/static

打包前清空

我們修改了文件之后,每次打包都會在 dist 目錄下產生一個新的 main.[hash].js , 隨著我們打包次數的增加,dist 目錄下會生產出一堆的 main.[hash].js,不出意外,你的dist目錄應該已經有不少了~

為了保證我們每次看到的都是最新的打包資源,而不受之前打包文件的干擾,這里我們需要引入另一個插件—— clean-webpack-plugin

  • 通過 npm install clean-webpack-plugin -D 下載插件
  • webpack.config.jsplugins 下去配置它
plugins:[
    new CleanWebpackPlugin()
]

pass:該插件引入方式是稍微有點不同,通過以下這種方式引入:

const { CleanWebpackPlugin } = require('clean-webpack-plugin')

現在,每次打包前都會先清空 dist 目錄下的文件,然后才產出打包后的文件,這樣看起來就清晰多了!

服務器代理

我們在開發時,有時候希望在同域名下發送 API 請求 ,那么代理某些 URL 會很有用,代理 API 的配置對于 webpack來說,配置就非常簡單了,只需要在 proxy 中添加代理規則即可

 proxy :  {
    "/api/test": {
     target: 'http://lohost:3000/', 
     secure: false,  
     changeOrigin: true, 
     pathRewrite: {
       '^/api/test': '/test'
    }
}

上面這行配置,就可以將 /api/test 開頭的接口地址,會被代理到 http://localhost:3000/test 下,如果是https接口,需要配置 secure 這個參數 為 true ,如果接口跨域,需要配置changeOrigin這個參數為 true

壓縮JS和CSS

我們現在打包出來的文件無論是 jscss 都是源文件,我們希望在打包的時候壓縮我們的代碼,一來是為了安全,二來是可以減少我們打包文件的體積。

我們選擇使用terser-webpack-plugin來壓縮js文件,替換掉之前的 uglifyjs-webpack-plugin,解決uglifyjs不支持es6語法問題,使用 optimize-css-assets-webpack-plugin 來壓縮 css 文件

  • 運行 npm install terser-webpack-plugin optimize-css-assets-webpack-plugin -D安裝插件
  • webpack.config.js 中引入并配置插件
new TerserPlugin({
    parallel: true,
    cache: true
}),
new OptimizeCSSAssetsPlugin({
    assetNameRegExp:/\.css$/g,
    cssProcessor:require('cssnano')
})

TerserPlugin 中的 parallel 代表開啟多進程,cache 代表設置緩存,OptimizeCSSAssetsPlugin 中加載了一個 cssnano 的東西, cssnanoPostCSSCSS優化和分解插件,會自動采用格式很好的CSS,并通過許多優化,以確保最終的生產環境盡可能小。

現在我們在繼續打包一次!

查看我們打包后的文件,可以發現 jscss 文件都沒打包成了一行,搞定!

結語

ok~ 看到這里,想必你對 webpack 已經有了一個比較完善的認識,對常見的一些配置打包的 loader 或者 plugin 都有一定的了解了,總結會發現,套路基本都差不多,需要什么 loaderplugin 只要去對應去查找即可~

emmm,其實 webpack 的功能非常強大,配置也是相當的多樣化,這里只是列舉了一些比較常見的功能,對你來說也只是一個拋磚引玉的作用,它的內部實現也是相當的復雜,想要真正弄懂 webpack ,還是需要多下一番苦功夫的~

對了,2019年還有幾個小時就結束了~

2020年,加油~

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,797評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,179評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,628評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,642評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,444評論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,948評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,040評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,185評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,717評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,602評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,794評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,316評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,045評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,418評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,671評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,414評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,750評論 2 370

推薦閱讀更多精彩內容