webpack簡介

一、簡介

webpack 是一個(gè)現(xiàn)代 JavaScript 應(yīng)用程序的靜態(tài)模塊打包器(module bundler)。主要是用來將前端資源打包、壓縮、優(yōu)化。

  • webpack 打包原理:
    當(dāng) webpack 處理應(yīng)用程序時(shí),不會(huì)根據(jù) package.json 文件中的devDependencies 或者 Dependencies 的內(nèi)容對文件進(jìn)行打包。而是會(huì)根據(jù)入口文件做查詢,加載其所依賴的包模塊,它會(huì)遞歸地構(gòu)建一個(gè)依賴關(guān)系圖(dependency graph),其中包含應(yīng)用程序需要的每個(gè)模塊,然后將所有這些模塊打包成一個(gè)或多個(gè) bundle。
  • 兩個(gè)最核心的概念:
    1.一切皆模塊
    正如js文件可以是一個(gè)模塊(module)一樣,其他的(如css、image或html)文件也可視作模塊。因此,你可以require(‘myJSfile.js’)也可以require(‘myCSSfile.css’)。這意味著我們可以業(yè)務(wù)分割成更小的易于管理的片段,從而達(dá)到重復(fù)利用的目的。
    2.按需加載
    傳統(tǒng)的模塊打包工具(module bundlers)最終將所有的模塊編譯生成一個(gè)龐大的bundle.js文件。但是在真實(shí)的app里邊,bundle.js文件可能有10M到15M之大,可能會(huì)導(dǎo)致應(yīng)用一直處于加載中狀態(tài)。因此Webpack使用許多特性來分割代碼然后生成多個(gè)bundle文件,而且異步加載部分代碼以實(shí)現(xiàn)按需加載。
二、安裝

webpack支持使用npm 或者 yarn 方式進(jìn)行安裝。不推薦全局安裝 webpack,這會(huì)將你項(xiàng)目中的 webpack 鎖定到指定版本,并且在使用不同的 webpack 版本的項(xiàng)目中,可能會(huì)導(dǎo)致構(gòu)建失敗。本地安裝可以使我們更容易對不同的項(xiàng)目進(jìn)行分別升級。通常,webpack 通過運(yùn)行一個(gè)或多個(gè) npm scripts,會(huì)在本地 node_modules 目錄中查找安裝的 webpack:

"scripts": {
    "start": "webpack"
}

如果使用 webpack 4+ 版本,還需要安裝 CLI。webpack-cli 可以允許直接在控制臺(tái)操作webpack命令。終端中輸入 webpack --help,可以查看所有的幫助信息。

使用npm安裝:
npm install webpack webpack-cli --save-dev
或者使用yarn安裝:
yarn add webpack webpack-cli -D

三、webpack基本概念

以以下目錄結(jié)構(gòu)為例來了解以下webpack的基本概念:


  • 入口 entry:在webpack.config.js配置文件中,通過設(shè)置entry字段的值,指定一個(gè)入口起點(diǎn)(或多個(gè)入口起點(diǎn)),不配置的話,默認(rèn)入口起點(diǎn)為src目錄下的index.js模塊。

默認(rèn)值為:

module.exports = {
    entry: './src'
    //相當(dāng)于
    entry:{ main:"/src/index.js" }
};

單頁面配置:

module.exports = {
    entry: './path/to/my/entry/file.js'
};

多頁面配置:

module.exports = {
    entry: {
      'main': "./src/js/index.js",
      'detail': "./src/js/detai.js"
  }
};
  • 輸出output :output 屬性告訴 webpack 在哪里輸出它所創(chuàng)建的 bundles,以及如何命名這些文件,默認(rèn)值為 ./dist?;旧?,整個(gè)應(yīng)用程序結(jié)構(gòu),都會(huì)被編譯到指定的輸出路徑的文件夾中??梢酝ㄟ^在配置中指定一個(gè) output 字段,來配置這些處理過程。

默認(rèn)值為:

const path = require('path');
module.exports = {
    output: {
        //path需要為絕對路徑
      path: path.resolve(__dirname, './dist'),
      filename: 'main.js'
    }
};

自定義配置:output 的 filename屬性中,使用[name]來表示entry中的key;使用[hash],會(huì)自動(dòng)在文件名稱后面添加hash值,并直接關(guān)聯(lián)到html模板文件中。

const path = require('path');
module.exports = {
    entry: {
        'main': "./src/js/index.js",
        'detail': "./src/js/detai.js"
    },
    output: {
        path: path.resolve(__dirname, './dev'),
        filename: '[name]-[hash].js'
    },
};
  • loader:loader 讓 webpack 能夠去處理那些非 JavaScript 文件(webpack 自身只理解 JavaScript)。簡單來說,loader 就是一個(gè)翻譯官,將瀏覽器不認(rèn)識(shí)的語言,轉(zhuǎn)化為瀏覽器能解析的語言,loader使用之前需要先安裝。loader 能夠 import 導(dǎo)入任何類型的模塊(例如 .scss 文件),這是 webpack 特有的功能,其他打包程序或任務(wù)執(zhí)行器的可能并不支持。

webpack.config.js文件:

module.exports = {
 module: {
   rules: [
     {
       test: /\.s[ac]ss$/,
       //當(dāng) use 里有多個(gè)loader時(shí),執(zhí)行的順序?yàn)閺挠蚁蜃?       use: [
         // 將 JS 字符串生成為 style 節(jié)點(diǎn),插入html中,生成內(nèi)聯(lián)樣式
         'style-loader',
         //將 CSS 轉(zhuǎn)化成 CommonJS 模塊,可以直接使用import/require導(dǎo)入
         'css-loader',
         //把.scss文件文件轉(zhuǎn)換為.css文件
         'sass-loader'
       ]
     }
   ]
 }
};

在webpack.config.js文件中,對一個(gè)單獨(dú)的 module 對象定義了 rules 屬性,里面包含兩個(gè)必須屬性:test 和 use。這告訴 webpack 編譯器(compiler) 如下信息:當(dāng)編譯器碰到「在 require()/import 語句中被解析為 ‘.sass/.scss’ 的路徑」時(shí),在對它打包之前,先使用 sass-loader、css-loader、style-loader 轉(zhuǎn)換一下。最終.scss文件會(huì)被轉(zhuǎn)成內(nèi)聯(lián)樣式,插入html頁面中。

  • plugins 插件:loader 被用于轉(zhuǎn)換某些類型的模塊,而插件則可以用于執(zhí)行范圍更廣的任務(wù),插件的范圍包括,從打包優(yōu)化和壓縮,一直到重新定義環(huán)境中的變量。想要使用一個(gè)插件,只需要 require() 它,然后把它添加到 plugins 數(shù)組中。多數(shù)插件可以通過選項(xiàng)(option)自定義,也可以在一個(gè)配置文件中因?yàn)椴煌康亩啻问褂猛粋€(gè)插件,這時(shí)需要通過使用 new 操作符來創(chuàng)建它的一個(gè)實(shí)例。

webpack.config.js文件:

//html-webpack-plugin 將html模板文件和js文件整合到一起
const htmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
    plugins: [
        new HtmlWebpackPlugin({
            //模板文件路徑
            template: "./src/views/index.html",
            //自動(dòng)存儲(chǔ)到output 配置的目錄
            filename: 'index.html',
            chunks: ['main']
        })
    ]
};

html-webpack-plugin 插件的作用是將html模板文件和js文件整合到一起,如果是多頁面應(yīng)用,則每個(gè)頁面都需要有對應(yīng)的new HtmlWebpackPlugin()。webpack在編譯的時(shí)候,會(huì)把所有的 js 合并輸出在一個(gè)js文件,而設(shè)置 chunks 屬性的目的,就是讓當(dāng)前頁面模板只加載當(dāng)前頁面所需要的模塊。上面的寫法表示,在編譯./src/views/index.html 時(shí),只需要加載main.js文件。

四、webpack配置
  • mode 模式
    mode 配置選項(xiàng),告知 webpack 使用相應(yīng)模式的內(nèi)置優(yōu)化。有兩個(gè)值:development(開發(fā)模式不會(huì)對代碼做壓縮、優(yōu)化,方便代碼調(diào)試,會(huì)將 process.env.NODE_ENV 的值設(shè)為 development)和production(生產(chǎn)模式下會(huì)對代碼做壓縮、優(yōu)化,會(huì)將 process.env.NODE_ENV 的值設(shè)為 production)。如果不配置mode,會(huì)有警告信息,但是不影響項(xiàng)目運(yùn)行。
module.exports = {
    mode:"development",
};
  • devtool
    開發(fā)模式通常配合devtool使用,可以在瀏覽器的控制臺(tái)看到源代碼,而不是解析后的代碼。
module.exports = {
    //代碼調(diào)試,可以看到源代碼
    devtool: 'inline-source-map',
};
  • webpack-dev-server
    在開發(fā)模式下,新建一個(gè)開發(fā)服務(wù)器,并且當(dāng)代碼更新的時(shí)候自動(dòng)刷新瀏覽器??梢允褂脀ebpack-dev-server插件。直接使用webpack執(zhí)行,會(huì)對文件進(jìn)行打包,并輸出在指定目錄下,默認(rèn)為./dev下。使用webpack-dev-server執(zhí)行,文件會(huì)放在內(nèi)存里,不會(huì)生成整合后的文件,也不會(huì)將文件輸出到指定目錄里。
    在webpack.config.js文件中配置
module.exports = {
    devServer:{
        contentBase:"./dist", //設(shè)置Http服務(wù)器的文件根目錄
        port:8088, //端口
        open:true, //是否打開瀏覽器
        proxy: { //配置代理
          "/api": {
                target: "http://localhost:3000",
                pathRewrite: {"^/api" : ""}
          }
        }
    }
};
  • webpack.config.js
    一個(gè)開發(fā)模式下,完整的webpack.config.js文件內(nèi)容如下:
const path=require("path");
//將html模板和js文件整合在一起
const htmlWebpackPlugin=require("html-webpack-plugin");
//將css樣式提取出來,使用Link標(biāo)簽導(dǎo)入
const miniCssExtractPlugin=require("mini-css-extract-plugin");
//將靜態(tài)資源打包到輸出目錄中
const copyWebpackPlugin=require("copy-webpack-plugin");

module.exports={
    mode:"development",
    devtool:"inline-source-map",
    entry:"./src/js/index.js",
    output:{
        path:path.resolve(__dirname+"./dev"),
        filename:"[name]-[hash].js"
    },
    devServer:{
        port:8088,
        open:true,
        proxy: { //配置代理
          "/api": {
                target: "http://localhost:3000",
                pathRewrite: {"^/api" : ""}
          }
        }
    },
    plugins:[
        new htmlWebpackPlugin({
            title:"demo title",
            template:"./src/views/index.html",
            filename:"index.html",
            chunks:["main"]
        }),
        new miniCssExtractPlugin({
            filename:"[name]-[hash].css"
        }),
        new copyWebpackPlugin([
            {from:"./src/static",to:"./static"}
        ])
    ],
    module:{
        rules:[
            {
                test:/\.s[ac]ss$/,
                use:[
                    miniCssExtractPlugin.loader,
                    "css-loader",
                    "sass-loader"
                ]
            },        
            {
                test:/\.html$/,
                use:["string-loader"]
            }
        ]
    }
}

package.json文件內(nèi)容如下:

{
  "name": "admin-fe",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dev": "webpack-dev-server --config webpack.config.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "handlebars": "^4.7.3",
    "sme-router": "^0.12.8"
  },
  "devDependencies": {
    "copy-webpack-plugin": "^5.1.1",
    "css-loader": "^3.4.2",
    "html-webpack-plugin": "^4.0.1",
    "mini-css-extract-plugin": "^0.9.0",
    "node-sass": "^4.13.1",
    "sass-loader": "^8.0.2",
    "string-loader": "^0.0.1",
    "style-loader": "^1.1.3",
    "webpack": "^4.42.1",
    "webpack-cli": "^3.3.11",
    "webpack-dev-server": "^3.10.3"
  }
}
五、webpack優(yōu)勢

與其他的構(gòu)建工具相比,webpack具有如下的一些優(yōu)勢:

  • 對 CommonJS 、 AMD 、ES6 的語法做了兼容
  • 對 js、css、圖片等資源文件都支持打包
  • 串聯(lián)式模塊加載器以及插件機(jī)制,讓其具有更好的靈活性和擴(kuò)展性,例如提供對 CoffeeScript、ES6的支持
  • 有獨(dú)立的配置文件 webpack.config.js
  • 可以將代碼切割成不同的 chunk,實(shí)現(xiàn)按需加載,降低了初始化時(shí)間
  • 支持 SourceUrls 和 SourceMaps,易于調(diào)試
  • 具有強(qiáng)大的 Plugin 接口,大多是內(nèi)部插件,使用起來比較靈活
  • webpack 使用異步 IO 并具有多級緩存,這使得 webpack 很快且在增量編譯上更加快
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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