12個常見的實戰場景 - [webpack 第二篇]

webpack實戰系列全目錄

  1. webpack6個常見的基礎配置知識點
  2. webpack 12個常見的實際場景
  3. webpack15個常見的優化策略【敬請期待】
  4. webpack從0打造兼容ie8的腳手架【敬請期待】
  5. webpack面試全總結【敬請期待】

本節咱們將要說到的實戰場景目錄:javascript

  1. 入門配置
  2. 建立單頁面應用
  3. 接入babel
  4. 接入scss
  5. 接入vue
  6. 分離javascript與css
  7. 壓縮javascript
  8. 壓縮css
  9. 提取javascript公共代碼
  10. 加入代碼規範檢測
  11. 搭建本地服務
  12. 建立多頁面應用

一: 入門配置

目錄結構以下: css

webpack.config.js配置以下:html

const path = require('path');
module.exports = {
    entry: './main.js',
    output: {
        filename: 'bundle.js',
        path: path.resolve(__dirname, 'dist') //必須是絕對路徑
    }
};
複製代碼

以上是一個最基礎的配置,咱們接下來一步一步的加入更多的功能.vue

二:單頁面應用

認識單頁面應用

首先,咱們經過第一節,能夠知道了怎麼將一個入口main.js打包成bundle.js了,那麼入口文件確定是要引用在html中啊,那麼,怎麼建立html文件?怎麼建立build之後的html文件,以及html文件如何引用入口js文件?答案就是 html-webpack-plugin。 點擊查看官方文檔java

該插件能夠實現哪些功能呢?node

  1. 不用咱們手動建立html文件,引用該插件之後,build後會自動生成一個index.html
  2. 生成的index.html不須要手動引入入口js文件,它會自動建立script標籤,而且引用生成的bundle.js

建立單頁面應用

第一步:安裝插件react

npm i html-webpack-plugin --save-dev
複製代碼

第二步:配置插件jquery

const HtmlWebpackPlugin = require('html-webpack-plugin');

plugins: [
    new HtmlWebpackPlugin({
        filename: 'index.html',
        template: './index.html'
    })
]
說明:
template:表示模版,即以哪一個html文件爲模,在dist目錄下生成新的html文件
filename: 即編譯之後生成的html文件的名字
複製代碼

注意:上面咱們說到不用咱們手動建立一個html文件,就能夠在編譯後自動生成一個index.html, 固然,咱們也能夠建立一個html模版文件,而後經過template屬性引入, 這樣編譯後生成的index.html內容就是咱們本身建立的模版html文件的內容)webpack

如下是咱們生成的index.html文件: es6

三: 接入babel

1. 認識babel

babel完成了兩件事情:

  1. 它是一個javascript解釋器,它能夠將es6代碼轉換爲es5代碼,讓咱們在使用語言新特性的時候,不用擔憂兼容性問題。
  2. 它能夠經過插件機制,根據需求靈活的拓展。

在 Babel 執行編譯的過程當中,會從項目根目 錄下 的 .babelre 文件中讀取配置。 .babelrc 是一個 JSON 格式的文件,內容大體以下:

{
  "presets": [
    ["env", {
      "modules": false,
      "targets": {
        "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
      }
    }],
    "stage-2",
    "react"
  ],
  "plugins": ["transform-vue-jsx", "transform-runtime"]
}

複製代碼

咱們來認識一下這兩個屬性:

  1. presets: 告訴babel要轉換的源代碼用了哪些新的語法特性,例如,react,es6等均可以在presets去聲明,表示咱們的源代碼中使用了react,es6等語法新特性。
  2. plugins: 用於告訴babel使用了哪些插件,而後babel就能夠經過這些插件去控制如何轉換代碼。經常使用的的插件是:transform-runtime, 全名是:babel-plugin-transform-runtime,即在前面加上了 babel-plugin-。它的做用是用於減小冗餘的代碼, 點擊查看babel將es6轉換成es5過程當中冗餘代碼分析

2. 接入babel

第一步:在webpack中配置babel-loader。

module.exports = { 
    module: {
        rules : [
            {
                test: /\.js$/ ,
                use : ['babel-loader'],
            }
            //此處還能夠在rules下配置其餘loader
        ]
    }
}
複製代碼

第二步:在根目錄下建立.babelrc文件,配置presets和plugins

{
    "presets": [
        "env"
    ],
    "plugins": []
}
複製代碼

注意:webpack4.x支持在package.json中直接配置babel屬性,不用新建.babelrc便可

"babel": {
        "presets": [
            "env"
        ],
        "plugins": []
    }
複製代碼

第三步:安裝babel相關依賴

# Webpack 接入 Babel 必須依賴的模塊
npm i -D babel-core babel-loader 
#根據咱們的需求選擇不一樣的 Plugins 或 Presets 
npm i -D babel-preset-env
複製代碼

提示:以上實例代碼主要用於說明整個接入webpack的過程,在不一樣場景下,具體的配置和安裝依賴狀況也會有所不一樣。

四:SCSS

認識scss

scss 即爲了咱們書寫css更方便且更有效率,出現了less,sass,scss等css的預處理器,那麼,在最後部署上線的時候,依然要轉成css,才能夠在瀏覽器端運行。

接入scss

第一步:安裝依賴

#安裝 Webpack Loader 依賴
npm i -D sass-loader css-loader style-loader 

# sass-loader 依賴 node-sass
npm i 一D node-sass
複製代碼

第二步:在module中配置

module:{
    rules:[
        {
            test: /\.scss$/,
            use: ["style-loader", "css-loader", "sass-loader"]
        }
    ]
}
複製代碼

說明:

  1. 當有多個loader的時候,編譯順序是從後往前
  2. sass-loader: 首先經過sass-loader將scss代碼轉換成css代碼,再交給css-loader處理
  3. css-loader 會找出 css 代碼中 import 和 url ()這樣的導入語句,告訴 Webpack 依賴這些資源 。 同時支持 CSS Modules、壓縮 css 等功能 。處理完後再將結果交給 style-loader處理。
  4. style-loader會將 css代碼轉換成字符串後,注入 JavaScript代碼中,經過 JavaScript 向 DOM 增長樣式。

以上是配置wepbakc接入scss的基本配置, 除此以外,咱們還能夠加入優化配置:

  1. 壓縮css
  2. css與js代碼分離:ExtractTextPlugin 這兩點在咱們項目開發中,也是須要配置的,以後咱們會講到。

五:使用vue框架

認識vue

你們可能都知道,vue,react等都是近些年來比較流行的mvvm框架,而咱們使用的過程當中,更可能是依賴vue-cli等自帶的腳手架去生成項目模版,不須要咱們手動去配置,那麼接下來,咱們就經過webpack去手動接入vue,這樣有利於咱們更好的理解vue。

接入vue

第一步:安裝依賴

# Vue 框架運行須要的庫
npm i -S vue
#構建所需的依賴
npm i -D vue-loader css-loader vue-template-compiler
複製代碼

說明:

  1. vue-loader:解析和轉換.vue文件,提取出其中的邏輯代碼 script、樣式代 碼 style及 HTML模板 template,再分別將它們交給對應的 Loader去處理。
  2. css-loader:加載由 飛rue-loader 提取出 的 css 代碼 。
  3. vue-template-compiler:將 vue-loader 提取出的 HTML 模板編譯成對應 的可執行的 JavaScript代碼,這和 React中的 JSX語法被編譯成 JavaScript代碼類 似 。 預先編譯好 HTML 模板相對於在瀏覽器中編譯 HTML 模板,性能更好 。

第二步:配置loader

const VueLoaderPlugin = require('vue-loader/lib/plugin');
module:{
    rules:[
        {
            test: /\.vue$/,
            use: 'vue-loader'
        }
    ]
},
plugins: [
    new VueLoaderPlugin()
],
複製代碼

注意:須要配置VueLoaderPlugin 插件,

提示:Vue-loader在15.*以後的版本都是 vue-loader的使用都是須要伴生 VueLoaderPlugin的

第三步:引入vue文件

//此時就和vue-cli提供的模版main.js同樣去引入vue和vue相關文件
import Vue from 'vue';
import App from './app.vue';
new Vue({
    el: '#app',
    render: h => h(App)
});

複製代碼

六:javascript與css處理

1. 分離javascript與css

默認狀況下,咱們打包entry入口文件的時候,文件中所依賴的css等樣式模塊也會包含js中,那麼,如何分離javascript和css,分別存放在不一樣的文件中呢?

第一步:安裝依賴

說明:Webpack 4.x已經再也不支持extract-text-webpack-plugin,推薦使用mini-css-webpack-plugin, 若是想繼續使用該插件,請 參考該文檔

此處,咱們依然用該插件來實現js與css的代碼分離:

//安裝插件
npm i extract-text-webpack-plugin@next --save-dev 

注意: 後面的@next必須加上,webpack4.x只支持該版本
或者能夠用一個新插件: mini-css-extract-plugin  
複製代碼

第二步:增長webpack配置

const ExtractTextPlugin = require ('extract-text-webpack-plugin');
module.exports = {
    module:{
        rules:[
            {
                test: /\.css$/,
                use: ExtractTextPlugin.extract({
                    fallback: "style-loader",
                    use: "css-loader"
                })
            }
        ]
    },
    plugins: [
        new ExtractTextPlugin({
            filename: path.resolve(__dirname, '/style/bundle.css') //注意能夠指定分離出來的css文件的指定目錄
        })
    ]
};
複製代碼

此時,咱們就能夠在build之後的dist文件夾裏,看到分離出來的css文件了。

例如:下面是一個文件目錄結構:

咱們在main.js中引入了main.css這個樣式文件,那麼,經過咱們webpack打包,而且進行javascript與css分離,dist中就分別生成了獨立的js文件和css文件。

2. 壓縮css

經過上面的操做,咱們已經將javascript與css分離開來,打開css文件,咱們發現,此刻css文件是位被壓縮的,

那接下來,咱們接入css壓縮相關配置: 第一步:安裝依賴

npm i optimize-css-assets-webpack-plugin --save-dev
複製代碼

第二步:添加配置

const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
module.export = {
    plugins: [
        //只要配置了該插件,便可對分離出來的css進行壓縮
        new OptimizeCssAssetsPlugin()
    ]
}
複製代碼

最後,咱們再次build,發現dist中css已是被壓縮的了。

3. 壓縮javascript

首先說明一點,可能咱們會看到不少教程使用的是UglifyJsPlugin,不過是webpack4.x以前的版本可使用,webpack4.x已經不支持使用移除webpack.optimize.UglifyJsPlugin 壓縮配置了, 推薦使用 optimization.minimize 屬性替代。

代碼以下:

module.exports = {
    optimization: {
        minimize: true //webpack內置屬性,默認爲true,
    }
}
複製代碼

注意:minimize屬性默認爲 true,即默認狀況下build以後的js文件已是壓縮的了,若是咱們不想壓縮js,能夠設置該屬性爲false,

咱們來看看實際壓縮先後的區別:

4. 提取公共javascript

一: 首先,咱們說明一下爲何要提取公共代碼?

大型網站一般由多個頁面組成, 每一個頁面都是一個獨立的單頁應用。 但因爲全部頁面都 採用一樣的技術枝及同 一套樣式代碼,就致使這些頁面之間有很 多相同的代碼。

若是每一個頁面的代碼都將這些公共的部分包含進去,則會形成如下問題 。

  1. 相同的資源被重複加載,浪費用戶的流量和服務器的成本。
  2. 每一個頁面須要加載的資源太大,致使網頁首屏加載緩慢, 影響用戶體驗。

因此,在實際開發過程當中,咱們須要把公共的代碼抽離成一個獨立的文件,這樣用戶在首次訪問網站是就加載了該獨立公共文件,此時這些公共文件就被瀏覽器緩存起來了,切換到其餘頁面時,該公共文件就不用在從新請求,而是直接訪問緩存接口。

二:實際開發中,都須要咱們提取哪些公共文件呢

一說到公共文件,咱們可能最早想到是一些公共的工具函數所在的common.js文件,這個公共文件中的工具函數會被多個頁面同時使用,其實,還有一個base.js也就是最基礎的文件,例如,咱們vue開發過程當中的vue.js,

因此,此處所說的公共文件包含如下兩部分:

  1. common.js (手動建立)
  2. base.js (引入的第三方依賴:如vue.js,lodash,jquery等)

注意:此處咱們爲何要把base.js也單獨提取出來,而不是直接包含在common.js中呢? 答案:爲了長期長期緩存base.js文件,

由於base.js中包含的都是一些基礎庫,並且是指定版本的,咱們平時開發過程當中,通常不會升級這些基礎庫的版本,全部只要基礎庫版本不升級,文件內容就不會變化,hash值也不會更新,那麼以前在瀏覽器中留下的緩存也不會被更新,從而實現長期緩存。而common.js是依據咱們開發的內容來的,因此若是開發過程當中發生了變化,那麼hash也變化,從新上線之後再次訪問,原來的緩存的common.js就沒法使用了,會使用新的common.js文件。

三: 最後,咱們來因此說一下,如何經過webpack提取公共代碼?

首先說明如下:webpack4.x提取公共代碼推薦使用:webpack內置的SplitChunksPlugin插件,4.x以前所使用的CommomsChunksPlugin已被淘汰

接下來,咱們來經過具體的例子試一下:

第一步:咱們建立了兩個入口文件:main.js 和 index.js, 還有一個公共的common.js文件,同時再安裝一個lodash第三方庫,而後兩個入口文件中,分別引入common.js和lodash;

// mian.js和index.js
import './assets/js/common';
import 'lodash';
複製代碼

第二步:配置多入口文件:

module.export = {
    entry: {
        main: './src/main.js',
        index: './src/index.js'
    },
    output: {
        filename: '[name].bundle.js',
        path: path.resolve(__dirname, 'dist')
    }
}
複製代碼

第三步:此時,咱們執行npm run build命令,生成的dist文件夾以下:

此時,咱們引入的lodash和common.js其實分別在main.bundle.js和index.bundle.js各打包了一份,很顯然,這樣是不對的,那麼如何把common.js和lodash分離打包成獨立的文件呢? 答案就是splitChunks屬性

第四步:配置splitChunks屬性

module.exports = {
    optimization: {
        splitChunks: {
            chunks: "async",
        }
    }
}
複製代碼

此時,咱們執行npm run build發現 dist中的文件沒有任何變化,並無將 公共模塊分離出來,緣由是爲何呢?

webpack4.x其實默認會將公共文件抽取出來的,只不過chunks屬性默認是async, 顧名思義該詞是異步的意思,也就是說默認狀況下,webpack4.x只會將異步的公共模塊分離成獨立的文件, 而咱們手動引入的common.js和lodash是同步引入的,因此沒有分離出來,因此咱們須要把chunks屬性改成‘initial’ 或者‘all’

module.exports = {
    optimization: {
        splitChunks: {
            chunks: "initial",
        }
    }
}
複製代碼

咱們再來看一下dist目錄:

咦,有了,多了一個vendors~index~main.bundle.js, 也就是說common.js和lodash已經分離出來了,都被存放在 vendors~index~main.bundle.js 中,

可是還差一步:如何讓common.js和lodash分別分離成獨立的文件呢?

首先,咱們分析如下緣由,實際上是minSize屬性致使的,它默認值爲30000,也就是說webpack4.x只會將文件大小大於3k的公共文件分離出來,而咱們目前的common.js大小還不夠,因此沒有單獨分離成一個文件,很顯然,此時只須要修改minSize的值便可。

module.exports = {
    optimization: {
        splitChunks: {
            chunks: "initial",
            minSize: 0
        }
    }
}
複製代碼

咱們再來看看dist目錄:

啦啦啦,終於搞定了,lodash等屬於nodemules中的公共依賴,都被分離到vendors~index~main.bundle.js中,而common.js被分離到main~index.bundle.js中,至此,如何提取公共js文件,大功告成!

七:認識npm script

Npm Script Chttps://docs.npm s.com/misc/scripts)是一個任務執行者。 Npm 是在安裝 Node.js 時附帶的包管理器, Npm Script 則是 Npm 內置的 一個功能,容許在 package.json 文件裏 使用 scripts 宇段定義任務:

{
   "scripts": {
       'dev': 'node dev.js',
       'build': 'node bulid.js'
   } 
}
複製代碼

以上代碼中的 scripts 字段是 一 個對象,每一個屬性對應一段腳本,以上代碼定義 了兩 個任務 dev 和 build。 Npm Script 的底層實現原理是經過調用 Shell 去運行腳本命令, 例如執 行 npm run build 命令等同於執行 node build.j s 命令。

同時npm script能夠執行node_modules內置的模塊:

例如:

  1. 咱們經過npm i webpack --save-dev 安裝了webpack
  2. 此時,咱們就能夠在npm script配置build命令,其實執行的就是webpack命令
{
    "scripts": {
        "build": "webpack"
    }
}
複製代碼

八:代碼規範檢測

前言

檢查代碼時主要檢查如下幾項:

  1. 代碼風格:讓項目成員強制遵照統一的代碼風格,例如如何縮緊、如何寫 註釋等, 保障代碼的可讀性,不將時間浪費在爭論如何使代碼更好看上。
  2. 潛在問題 : 分析代碼在運行過程當中可能出現的潛在 Bug。

檢查javascript

目前最經常使用的 JavaScript 檢查工具是 ESlint (eslint.org),它不只內 置了大量的經常使用檢查 規則,還能夠經過插件機制作到靈活擴展。

  1. 單獨使用 第一步:安裝eslint
npm i eslint --save-dev //局部安裝
或者
npm i eslint -g //全局安裝
複製代碼

第二步:建立.eslintrc

{
    //從 eslint :recommended 中繼承全部檢查規則 
    "extends" : "eslint:recommended",
    // 再自定義一些規則
    」rules」:{
        //須要在每行結尾加 ;
        "semi":["error""always"] , //須要使用""包裹字符串
        "quotes" : [ "error", "double"]
    }
}
複製代碼

第三步:運行eslint命令

eslint yourfile . js
複製代碼

該命令的做用就是檢查yourfile.js文件的代碼格式是否符合eslint的要求,若是有問題會報警提示:例如:

296:13 error Strings must use doublequote quotes 
298 :7 error Missing semicolon sem工
複製代碼
  1. webpack接入eslint 第一步:安裝eslint-loader
npm i eslint-loader -D
複製代碼

第二步:添加loader

module: {
    rules: [
        {
            test: /\.js$/,
            use: {
                loader: 'eslint-loader',
                options: {
                    formatter: require('eslint-friendly-formatter') // 默認的錯誤提示方式
                }
            },
            enforce: 'pre', // 編譯前檢查
            exclude: /node_modules/, // 不檢測的文件
            include: [__dirname + '/src'], // 要檢查的目錄
        }
    ]
}
複製代碼

第三步:新建.eslintrc.js

複製代碼

檢查css

stylelint (stylelint.io)是目前最成熟的 css 檢查工具,在內置了大量檢查規則的 同時,也提供了插件機制讓用戶自定義擴展 。 stylelint 基於 PostCSS,能檢查任何 PostCSS 能解析的代碼,例如 scss、 Less 等 。

  1. 單獨使用 第一步:安裝stylelint
npm i stylelint --save-dev
或者
ηpm i -g stylelint
複製代碼

第二步:建立.stylelintrc文件

{
    
    //繼承 stylelint-config-standard 中全部的檢查規則 
    "extends":"stylelint-config-standard",
    // 再自定義檢查規則
    "rules": {
        "at-rule-empty-line-before": null
    }
}
複製代碼

第三步:執行命令

stylelint 」yourfile.css」 

複製代碼
  1. webpack中接入stylelint

搭建本地開發環境

第一步. 搭建本地服務webpack-dev-server

npm install webpack-dev-server --save-dev
複製代碼

第二步:在package.json配置npm script命令

scripts: {
    "dev": 'webpack-dev-server --config webpack.dev.config.js'
}
複製代碼

說明:此處咱們新建一個測試環境的webpack配置文件,用於區分正式環境和測試環境

第三步:配置devServer

module.exports = merge(baseWebpackConfig, {
    mode: 'development',
    devServer: {
        port: 9999,
        contentBase: './dist',
    },
    plugins: [
    ]
});
複製代碼

此時,咱們在瀏覽器中輸入:localhost:9999 就能夠訪問到咱們的頁面了。

第四步:實現實時刷新 即,只要代碼改動,保存之後,瀏覽器自動刷新

module.exports = merge(baseWebpackConfig, {
    mode: 'development',
    devServer: {
        inline: true, //實時刷新
    },
    plugins: [
    ]
});
複製代碼

第五步:實現熱更新

module.exports = merge(baseWebpackConfig, {
    mode: 'development',
    devServer: {
        hot: true, //熱替換
    },
    plugins: [
        // 熱更新插件
        new webpack.HotModuleReplacementPlugin()
    ]
});
複製代碼

注意一下三者的區別:

  1. 開啓本地服務:webpack-dev-server能夠啓動一個本地服務
  2. 實時刷新:代碼改動,瀏覽器整個頁面會自動刷新
  3. 熱更新:代碼改動,瀏覽器不會整個頁面都刷新,而是隻會在改動的地方局部更新。

十:多頁面應用

1. 認識多頁面應用

首先說明一下單頁面和多頁面的區別:

  1. 單頁面:只有一個html文件,頁面以前的跳轉經過路由機制去控制,平時咱們使用vue-cli等腳手架自動生成的模版都是單頁面,路由經過vue-router去控制跳轉。
  2. 多頁面:多個html文件,頁面之間的跳轉是經過瀏覽器原生的機制去控制,好比在沒有vue,react等框架以前,基本都是多頁面的開發。

2. 建立多頁面應用

  1. 方式1:建立多個入口文件,同時結合 html-webpack-plugin 建立多個html文件,實現多頁面應用

  2. 方式2: 使用web-webpack-plugin 插件

說明:此處暫不說明具體配置,你們只需清除單頁面和多頁面的區別,同時,能夠採用一下兩種方式去實現多頁面應用。

總結

經過本節的十幾個實戰場景,相信你們已經基本瞭解了webpack整個配置的機制,什麼場景下采用什麼樣的配置,固然,你們沒必要徹底記住具體的配置,但要知道什麼場景下,用什麼樣的loader或者plugin等, 同時,我的以爲最重要的是 理解這些場景下所蘊含的思想,例如爲何要區分出現單頁面?爲何要分離javascript與css?爲何壓縮文件等等,這些纔是最關鍵的,以後,咱們專門用一節去講述webpack背後所包含的這些思想,你們敬請期待吧!

相關文章
相關標籤/搜索