webpack4

1. 什么是webpack

webpack可以看做是模塊打包機(jī):它做的事情是,分析你的項目結(jié)構(gòu),
找到JavaScript模塊以及其它的一些瀏覽器不能直接運(yùn)行的拓展語言(Scss,TypeScript等),并將其打包為合適的格式以供瀏覽器使用。
構(gòu)建就是把源代碼轉(zhuǎn)換成發(fā)布到線上的可執(zhí)行 JavaScrip、CSS、HTML 代碼

代碼轉(zhuǎn)換:LESS、SCSS 編譯成 CSS 等。
文件優(yōu)化:壓縮 JavaScript、CSS、HTML 代碼,壓縮合并圖片等。
代碼分割:提取多個頁面的公共代碼、提取首屏不需要執(zhí)行部分的代碼讓其異步加載。
模塊合并:在采用模塊化的項目里會有很多個模塊和文件,需要構(gòu)建功能把模塊分類合并成一個文件。
自動刷新:監(jiān)聽本地源代碼的變化,自動重新構(gòu)建、刷新瀏覽器。
代碼校驗:在代碼被提交到倉庫前需要校驗代碼是否符合規(guī)范,以及單元測試是否通過。
自動發(fā)布:更新完代碼后,自動構(gòu)建出線上發(fā)布代碼并傳輸給發(fā)布系統(tǒng)。
  1. webpack核心概念
    Entry:入口,Webpack 執(zhí)行構(gòu)建的第一步將從 Entry 開始,可抽象成輸入。
    Module:模塊,在 Webpack 里一切皆模塊,一個模塊對應(yīng)著一個文件。Webpack 會從配置的 Entry 開始遞歸找出所有依賴的模塊。
    Chunk:代碼塊,一個 Chunk 由多個模塊組合而成,用于代碼合并與分割。
    Loader:模塊轉(zhuǎn)換器,用于把模塊原內(nèi)容按照需求轉(zhuǎn)換成新內(nèi)容。
    Plugin:擴(kuò)展插件,在 Webpack 構(gòu)建流程中的特定時機(jī)注入擴(kuò)展邏輯來改變構(gòu)建結(jié)果或做你想要的事情。
    Output:輸出結(jié)果,在 Webpack 經(jīng)過一系列處理并得出最終想要的代碼后輸出結(jié)果。
  1. 初始化package.json
    npm init -y

默認(rèn)約定webpack 的 4.x 版本中默認(rèn)約定
打包的 入口文件為 src -> index.js
打包的 輸出文件為 dist -> main.js

修改 修改打包的入口與出口,可以在 webpack.config.js 中新增加如下配置信息

const path = require('path') // 導(dǎo)入 node.js 中專門操作路徑的模塊 path
module.exports = {
entry: path.join(_dirname,'./src/index.js'),//打包入口文件的路徑
output: { 
        path: path.join(__dirname,'./dist'), // 輸出文件的存放路徑
        filename: 'bundle.js' //輸出文件的名稱
    }
}

配置自動打包

  1. npm install webpack-dev-server -D

-D 指安裝依賴到開發(fā)環(huán)境,上線環(huán)境使用 -S

  1. 修改 package.json 文件中 scripts 對象的 dev 命令,如下配置:
// package.json 中的配置
"scripts": {
    "dev": "webpack-dev-server --profile --progress --colors" // script 節(jié)點(diǎn)下的腳本,可以通過 npm run 執(zhí)行
  },

//--display-modules --profile --progress --colors --display-error-details

//color 輸出結(jié)果帶彩色,比如:會用紅色顯示耗時較長的步驟
//profile 輸出性能數(shù)據(jù),可以看到每一步的耗時
//progress 輸出當(dāng)前編譯的進(jìn)度,以百分比的形式呈現(xiàn)
//display-modules 默認(rèn)情況下 node_modules 下的模塊會被隱藏,加上這個參數(shù)可以顯示這些被隱藏的模塊
//display-error-details 輸出詳細(xì)的錯誤信息

將 src -> index.html 中,scripts 腳本的引用路徑 ,修改為根目錄下的 buldle.js

注意:
webpack-dev-server 會啟動一個實(shí)時打包的 http 服務(wù)器
webpack-dev-server 打包生成的輸出文件,默認(rèn)放到了項目根目錄中,而且是虛擬的,看不到的

// --open 打包完成后自動打開瀏覽器頁面  --host 配置 IP地址  --port 配置端口
"dev": "webpack-dev-server --profile --progress --colors --open --port 8888"

配置預(yù)覽頁面

  1. 在終端中運(yùn)行如下命令,安裝生成預(yù)覽頁面的插件
    npm install html-webpack-plugin -D
  2. 修改 webpack.config.js 文件頭部區(qū)域,添加如下配置信息:
// 導(dǎo)入生成預(yù)覽頁面的插件,得到一個構(gòu)造函數(shù)
const HtmlWebpackPlugin = require('html-webpack-plugin')
const htmlPlugin = new HtmlWebpackPlugin({//創(chuàng)建插件的實(shí)例對象
  template: './src/index.html',// 指定要用到的模版文件
  filename: 'index.html'//指定生成的文件的名稱,該文件存在于內(nèi)存中,在目錄中不顯示
})
  1. 修改 webpack.config.js 文件中向外暴露的配置對象 ,新增如下配置節(jié)點(diǎn):
module.exports = {
  plugins: [ htmlPlugin ] //plugin 數(shù)組是 webpack 打 包期間會用到的一些插件列表
}

2. 配置webpack

2.1 配置文件webpack.config.js

//entry:配置入口文件的地址
//output:配置出口文件的地址
//module:配置模塊,主要用來配置不同文件的加載器
//plugins:配置插件
//devServer:配置開發(fā)服務(wù)器
// 基于node的 遵循commonjs規(guī)范的
let path = require('path');
module.exports = {
    // 入口  
    entry: './src/index.js',
    // 出口  
    output: {
        filename: 'build.js',    // 這個路徑必須是絕對路徑    
        path: path.resolve('./dist')
    },
    // 開發(fā)服務(wù)器  
    devServer: {
        //contentBase 配置開發(fā)服務(wù)運(yùn)行時的文件根目錄
        contentBase: path.resolve(__dirname, 'dist'),
        //host:開發(fā)服務(wù)器監(jiān)聽的主機(jī)地址
        host: 'localhost',
        //port:開發(fā)服務(wù)器監(jiān)聽的端口
        port: 8080,
        //compress 開發(fā)服務(wù)器是否啟動gzip等壓縮
        compress: true,// 服務(wù)器壓縮    
        open: true,// 自動打開瀏覽器    
        // hot:true//熱更新 
    },
    module: {}, // 模塊配置  
    plugins: [], // 插件的配置  
    mode: 'development', // 可以更改模式  
    resolve: {}, // 配置解析}// 
    //在webpack中如何配置開發(fā)服務(wù)器 webpack-dev-server
}

//開啟本地服務(wù) npm run dev
"scripts": {
    "build": "webpack  --mode development  --profile --progress ",
    "dev": "webpack-dev-server --open --mode development  --profile --progress  "
}

2.2 入口文件的類型
單入口+單出口

entry: './src/index.js',

2.4 多入口數(shù)組形式+單出口

entry:['./src/index.js','./src/a.js']

2.4 多入口+多出口
有時候我們的頁面可以不止一個HTML頁面,會有多個頁面,所以就需要多入口

 npm i html-webpack-plugin  -D
let path = require('path');
let HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
    // 入口  
    entry: {
        index: './src/index.js',
        main: './src/main.js'
    },
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: '[name].[hash].js',
        publicPath: '/'
    },
    // 插件的配置  
    plugins: [
        new HtmlWebpackPlugin({
            minify: {
                removeAttributeQuotes: true, //刪除屬性雙引號
                collapseWhitespace: true //壓縮空白
            },
            hash: true,
            template: './src/index.html',
            chunks: ['index'],
            title: 'index',
            filename: 'index.html'
        }),
        new HtmlWebpackPlugin({
            minify: {
                removeAttributeQuotes: true, //刪除屬性雙引號
                collapseWhitespace: true //壓縮空白
            },
            hash: true,
            template: './src/index.html',
            chunks: ['main'],
            title: 'main',
            filename: 'main.html',
        })
    ]
}

2.5 我們可以使用插件來生成html文件,這樣就避免了html每次去手動引入js;使用插件來刪除上次打包的結(jié)果
使用CleanWebpackPlugin可以每次構(gòu)建前清空輸出目錄.
當(dāng)你多次打包的時候,你會發(fā)現(xiàn)由于使用hash來命名輸出的文件每次的文件名稱都不一樣,導(dǎo)致文件越來越多.

npm i -D html-webpack-plugin clean-webpack-plugin
//修改webpack.common.js文件
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');

module.exports = {
    ...
    plugins:[
        new HtmlWebpackPlugin({template:'./src/index.html'}),
        new CleanWebpackPlugin()
    ]
    ...
}

2.6 每次修改完文件都要重新打包才能看到效果,我們可以使用webpack-dev-server來搭建一個本地服務(wù)器來實(shí)時更新。

npm i -D webpack-merge
//webpack.dev.js
const merge = require('webpack-merge')
const common = require('./webpack.common')

module.exports = merge(common, {
    mode: 'development',
    devServer: {
        contentBase: './index.html',
        hot: true,
        port: 3000
    }
})

//修改package.json的dev
 "scripts": {
    "dev": "webpack-dev-server --open --config ./config/webpack.dev.js",  
    ...
  },

2.7 安裝babel

npm i -D @babel/preset-env babel-loader @babel/core
//webpack.common.js
module.exports = {
    module: {
        rules: [
            {
                test: /\.(js)$/,
                exclude: /(node_modules|bower_components)/,
                use: [
                    {
                        loader: 'babel-loader',
                        options: {
                            presets: ['@babel/preset-env']
                        }
                    }
                ]
            },
        ]
    }
}

2.8 處理css

npm i -D style-loader css-loader
//webpack.common.js
   ...
   module:{
    rules:[
        ...
        {
          test: /\.css$/,
          use: ['style-loader', 'css-loader']
        }
    ]
   }

//index.css
...
.red {
  color: red;
}

可以看到樣式被插進(jìn)了head中。當(dāng)項目變大時樣式直接插入head中的方式并不好,我們需要將樣式分離
webpack4的版本中建議使用mini-css-extract-plugin插件(以前是ExtractTextWebpackPlugin插件)

npm i -D mini-css-extract-plugin
//webpack.common.js
...
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

    rules:[
        ...
        {
          test: /\.css$/,
          use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: {
              // you can specify a publicPath here
              // by default it uses publicPath in webpackOptions.output
              publicPath: '../',
              hmr: process.env.NODE_ENV === 'development',
             },
            },
           'css-loader',
          ],
        }
    ]

plugins:[
    ...
     new MiniCssExtractPlugin({
      filename: 'static/css/[name].css',   //打包到static的css目錄下
      ignoreOrder: false, // Enable to remove warnings about conflicting order
    })
]

開發(fā)環(huán)境不存在這個,在生產(chǎn)環(huán)境中,打包的文件上傳服務(wù)器,被用戶使用后,會被緩存在瀏覽器時;當(dāng)需要修改代碼時,又重新打包上傳,而用戶的瀏覽器發(fā)現(xiàn)加載的文件名字一樣,就不會重新加載,還是會從緩存中加載,就造成了修改的代碼不能更新使用;
解決方法:每次打包的文件,都會有自己的hash值,只要文件修改,hash值才會變化,不修改,無論打包幾次,值都不會發(fā)送改變;

在webpack.prod.js生成配置中輸出時使用contenthash,這樣修改的文件名就會改變,而用戶的瀏覽器發(fā)現(xiàn)不一樣的文件,就會重新加載,相同名文件則不會加載,這有提高了性能

一個滾動插件https://www.npmjs.com/package/smooth-scroll

Shimming:墊片,解決某些問題

** webpack的核心就是模塊與模塊之間分開,**

** 但是當(dāng)有些公共模塊或庫需要在多個模塊中調(diào)用,**

** 或者比如有一些第三方庫使用了JQ的$,但是不是用import引用的,當(dāng)你調(diào)用時,不能識別,**

** 就可以在webpack的配置中引入webpack的插件ProvidePlugin**

以JQ為例,當(dāng)模塊使用時,就會自動在模塊頂部添加import from 'jquery'

通過懶加載的方式動態(tài)引入文件

const router = new Router({
    routes: [{
        path: '/home',
        name: 'Home',
        component: () =>
            import('./views/home/Home.vue')
    }]
})

解決方案

安裝插件babel-plugin-dynamic-import-webpack

npm install babel-plugin-dynamic-import-webpack --save-dev

在配置文件的module的rules下進(jìn)行插件的配置,如下

{
    test: /\.js/,
    use: [{
        loader: 'babel-loader', 
        options: {//如果有這個設(shè)置則不用再添加.babelrc文件進(jìn)行配置
            "babelrc": false,// 不采用.babelrc的配置
            "plugins": [
                "dynamic-import-webpack"
            ]
        }
    }]
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容