WebPack學(xué)習(xí)匯總

Webpack用于前端工程化代碼的底層構(gòu)建坪哄,angular奸腺、react、vue三大框架都采用了webpack來(lái)做構(gòu)建诵肛。webpack具備的功能:tree shaking、懶加載疆栏、代碼分割等等曾掂。其核心定義是一個(gè)模塊打包工具;
能夠識(shí)別所有模塊引入方式壁顶,例如:

  • es6 module import引入珠洗;
  • commonJs 中module.exports=Header;
  • AMD若专;
  • CMD许蓖;

Webpack 4的構(gòu)建速度更快,在構(gòu)建大型的項(xiàng)目時(shí)调衰,甚至可以提升90%的構(gòu)建速度膊爪。Nodejs和Webpack版本盡可能用最新穩(wěn)定(LTS)版本,也可以提高打包速度嚎莉;

會(huì)涉及的知識(shí)點(diǎn)如下圖:


image.png

安裝

新建一個(gè)米酬,webpack01文件夾,并cd webpack01進(jìn)入文件夾趋箩,安裝好需要的包webpack和webpack-cli赃额,并指定版本安裝(新版本尚未研究差異,暫且用老版本)叫确,其中webpack-cli用于實(shí)現(xiàn)命令行功能跳芳。
當(dāng)沒(méi)有使用-g進(jìn)行全局安裝時(shí),執(zhí)行webpack -v會(huì)提示命令不存在竹勉;需要使用npx webpack -v來(lái)執(zhí)行飞盆,npx會(huì)進(jìn)入到項(xiàng)目中的node_module目錄,尋找到webpack包來(lái)執(zhí)行;

//不推薦全局安裝-g
npm i webpack@4.43.0 webpack-cli@3.3.12 --save-dev
npm i webpack@4.43.0 webpack-cli@3.3.12-D

設(shè)置淘寶鏡像

在根目錄下創(chuàng)建.npmrc配置文件:

registry=https://registry.npm.taobao.rog/

其他方法:
1次乓、npm config set registry https://registry.npm.taobao.org
2吓歇、npm config set registry https://registry.npm.taobao.org/

重置webpack打包命令**

修改package.json文件的script屬性值,執(zhí)行npm run dev命令時(shí)票腰,等同于npx webpack

  "scripts": {
    "dev":"npx webpack",
    ...
  },

看一個(gè)入門(mén)小例子

  • 目錄結(jié)構(gòu)
    image.png
  • 代碼
    index.html的代碼
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>首頁(yè)</title>
</head>

<body>
    <div id="root"></div>
    <script src="./index.js"></script>
</body>

</html>

index.js的代碼

import Header from "./header";
import Content from "./content";
import Footer from "./footer";

new Header();
new Content();
new Footer();

header.js的代碼

function Header() {
    var dom = document.getElementById("root");

    var header = document.createElement("div");
    header.innerText = "header";
    dom.append(header);
}
export default Header;

content.js的代碼

function Content() {
    var dom = document.getElementById("root");

    var content = document.createElement("div");
    content.innerText = "content";
    dom.append(content);
}
export default Content;

footer.js的代碼

function Footer() {
    var dom = document.getElementById("root");

    var footer = document.createElement("div");
    footer.innerText = "footer";
    dom.append(footer);
}
export default Footer;
  • 運(yùn)行
    執(zhí)行命令npx webpack index.js完成后照瘾,會(huì)在項(xiàng)目根目錄下生成一個(gè)dist目錄,里面 有個(gè)main.js文件丧慈。打開(kāi)index.html,頁(yè)面顯示如下:
    image.png

Webpack默認(rèn)配置文件webpack.config.js

1. 入口(entry)
當(dāng)沒(méi)有創(chuàng)建webpack.config.js文件,或者此文件中為空時(shí)逃默,直接執(zhí)行npx webpack鹃愤,終端控制臺(tái)報(bào)錯(cuò);寫(xiě)入如下代碼:

module.exports = {
    entry: "./index.js"http://等同于{main:"./index.js"}完域,會(huì)在輸出目錄中打包生成main.js文件软吐。
};

再次執(zhí)行npx webpack,則在根目錄生成'/dist/main.js'吟税,效果等同于npx webpack index.js凹耙。
2. 出口(output)

const path = require('path');
module.exports = {
    entry: "./index.js",
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'my-first-webpack.bundle.js'
    }
};

執(zhí)行npx webpack,生成文件如下:

image.png

常用配置:

  • publicPath:"http://cdn.com.cn"肠仪,打包完成后肖抱,會(huì)在index.html中引入的script路徑中加上這個(gè)域名;
    image.png

3. mode模式
production:默認(rèn)异旧,代碼會(huì)被壓縮
development:代碼不會(huì)被壓縮
4. loader
webpack不能識(shí)別非 JavaScript 文件意述,需要loader來(lái)識(shí)別;如果看到引入的模塊的后綴不是.js吮蛹,就需要想到用對(duì)應(yīng)的loader來(lái)引入荤崇;loader中支持配置各種options參數(shù),例如:file-loader的選項(xiàng)值潮针;loader的執(zhí)行順序是由右往左的术荤。

常用的loader:

  • file-loader:指示webpack發(fā)出所需的對(duì)象文件,并返回其公共URL;可用于加載iconfont中的字體文件。
  • url-loaderurl-loader 功能類似于 file-loader每篷,但是在文件大邪昶荨(單位 byte)低于指定的限制時(shí),可以返回一個(gè) DataURL雳攘。
test: /\.(png|jpg|gif)$/, use: {
        loader: "url-loader",
        options: {
            name: 'images/[name].[ext]',
            limit: 8192//單位B带兜,如果不設(shè)置,則會(huì)把所有圖片都用base64
        }
    }
//js引入圖片需要使用require吨灭,直接寫(xiě)相對(duì)路徑無(wú)效
var img = new Image();
img.src = require('./image/img1.jpg').default;
document.getElementById("main").appendChild(img);
  • style-loader:將css文件中的內(nèi)容解析提取出來(lái)刚照,并掛載到head中style里面;
  • css-loader:解釋@importurl() 喧兄,會(huì)import/require()后再解析(resolve)它們无畔。例如css文件中使用@import "./avator.css";
  • sass-loader:加載一個(gè)SASS / SCSS文件,編譯成 CSS吠冤。安裝npm install sass-loader node-sass --save-dev
  • postcss-loaderPostCSS利用 JavaScript 的強(qiáng)大編程能力對(duì) CSS 代碼進(jìn)行轉(zhuǎn)換浑彰。數(shù)以百計(jì)的 PostCSS 插件可以用來(lái)為 CSS 屬性添加特定于瀏覽器廠商的前綴、壓縮工具cssnano拯辙、支持未來(lái) CSS 語(yǔ)法郭变、模塊颜价。如果給class添加廠商前綴
  • babel-loader:用來(lái)處理ES6語(yǔ)法,將其編譯為瀏覽器可以執(zhí)行的js語(yǔ)法诉濒;使用userBuildIns:'usage'配置周伦,可以有效減少打包文件大小(只打包用到的es6語(yǔ)法)未荒。使用target設(shè)定目標(biāo)瀏覽器版本专挪,打包的時(shí)候就會(huì)對(duì)這些版本下支持的es6語(yǔ)法免打包;
    再結(jié)合"@babel/polyfill"片排,可以完全解決es6在老瀏覽器中運(yùn)行問(wèn)題寨腔,但是打包文件也會(huì)因此而變大,因?yàn)橄到y(tǒng)會(huì)把很多老瀏覽器不支持的方法率寡,以自定義代碼的形式打包到文件中迫卢。所以要使用useBuiltIns:'usage',設(shè)置如果用到了就打包勇劣,沒(méi)用到就不打包靖避。高階前端工程師需要學(xué)習(xí)babel各種配置,了解抽象語(yǔ)法樹(shù)比默。

如果是寫(xiě)的項(xiàng)目代碼幻捏,那么可以用babel+@babel/polyfill來(lái);如果是發(fā)布上線的組件或插件命咐,就不能用這種方式篡九,會(huì)污染全局。需要改用@babel/plugin-transform-runtime

image.png
        rules: [
            {
                test: /\.js$/,
                exclude: /node_modules/,
                loader: "babel-loader",
                options: {
                    "presets": [
                        ["@babel/preset-env", {
                            "targets": {
                                "chrome": "67"
                            },
                            "useBuiltIns": "usage"
                        }]
                    ]
                }
            },

babel-loaderoptions配置項(xiàng)的代碼也可以單獨(dú)放入跟目錄下的.babelrc文件中醋奠,執(zhí)行效果是一樣的榛臼。

//vue init webpack my-project腳手架項(xiàng)目默認(rèn).babelrc文件代碼
{
  "presets": [
    ["env", {
      "modules": false,
      "targets": {
        "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
      }
    }],
    "stage-2"
  ],
  "plugins": ["transform-vue-jsx", "transform-runtime"],
  "env": {
    "test": {
      "presets": ["env", "stage-2"],
      "plugins": ["transform-vue-jsx", "transform-es2015-modules-commonjs", "dynamic-import-node"]
    }
  }
}

5. plugins
插件目的在于解決 loader 無(wú)法實(shí)現(xiàn)的其他事;可以在webpack運(yùn)行到某個(gè)時(shí)刻的時(shí)候窜司,幫你做一些事情沛善;類似于生命周期鉤子;例如html-webpack-plugin查看塞祈,就是在webpack打包完成的時(shí)刻金刁,自動(dòng)生成一個(gè)index.html到打包目錄中去。
常用plugins:

  • html-webpack-plugin:自動(dòng)生成一個(gè)HTML文件
  • clean-webpack-plugin:清空打包目錄
  • webpack.ProvidePlugin议薪,例如引入jquery
//安裝
npm install jquery --save-dev
//引用尤蛮,修改webpack.config.js文件。
const webpack = require('webpack')
plugins: [
        new webpack.ProvidePlugin({
            jQuery: "jquery",
            $: "jquery"
        })
    ],
//使用
$("#header").html("init");

6. sourceMap

devtool用于打包前和打包后文件代碼位置映射斯议,方便代碼出錯(cuò)時(shí)定位到源代碼位置产捞;

當(dāng) webpack 打包源代碼時(shí),可能會(huì)很難追蹤到錯(cuò)誤和警告在源代碼中的原始位置哼御。例如坯临,如果將三個(gè)源文件(a.js, b.jsc.js)打包到一個(gè) bundle(bundle.js)中焊唬,而其中一個(gè)源文件包含一個(gè)錯(cuò)誤,那么堆棧跟蹤就會(huì)簡(jiǎn)單地指向到 bundle.js看靠。這并通常沒(méi)有太多幫助求晶,因?yàn)槟憧赡苄枰獪?zhǔn)確地知道錯(cuò)誤來(lái)自于哪個(gè)源文件。

為了更容易地追蹤錯(cuò)誤和警告衷笋,JavaScript 提供了 source map 功能,將編譯后的代碼映射回原始源代碼矩屁。如果一個(gè)錯(cuò)誤來(lái)自于 b.js辟宗,source map 就會(huì)明確的告訴你。 devtool詳細(xì)配置吝秕、JavaScript Source Map 詳解

module.exports = {
    entry: {
      app: './src/index.js',
      print: './src/print.js'
    },
    devtool: 'cheap-module-eval-source-map',  //調(diào)試版本建議用
    //devtool: 'cheap-module-source-map',      //打包后版本建議用
    plugins: [
      new CleanWebpackPlugin(['dist']),
      new HtmlWebpackPlugin({
        title: 'Development'
      })
    ],
    output: {
      filename: '[name].bundle.js',
      path: path.resolve(__dirname, 'dist')
    }
  };

7. devServer
用于調(diào)試階段項(xiàng)目熱重載泊脐;

  • a.安裝;npm i webpack-dev-server -D
  • b.修改webpack.config.js
    devServer: {
        contentBase: path.join(__dirname, "dist"),//
        compress: true,
        open: true,
        port: 9000
    },
  • c.修改package.json
  "scripts": {
    "watch": "webpack --watch",//觀察者模式烁峭。源代碼更改后容客,dist中代碼會(huì)自動(dòng)打包;
    "start": "webpack-dev-server"http://npm run start啟動(dòng)后约郁,會(huì)自動(dòng)打開(kāi)一個(gè)端口為9000的頁(yè)面缩挑,并且源代碼修改后,頁(yè)面會(huì)熱重載鬓梅;
  }

package.json配置

  1. 修改打包命令
  "scripts": {
    "bundle": "webpack"http://可以不用寫(xiě)npx webpack供置,因?yàn)閟cript腳本命令,會(huì)優(yōu)先到當(dāng)前工程目錄中查找是否支持此命令绽快,沒(méi)找到再到全局查找芥丧;
    "watch": "webpack --watch",//監(jiān)聽(tīng)模式,如發(fā)現(xiàn)源代碼改變了坊罢,則將文件自動(dòng)打包到dist目錄(頁(yè)面不會(huì)自動(dòng)刷新)
    "start": "webpack-dev-server"http://自動(dòng)熱重載续担,如果發(fā)現(xiàn)域代碼改變了,則自動(dòng)打包到內(nèi)存活孩,并自定刷新瀏覽器頁(yè)面
  },

執(zhí)行npm run bundle物遇,等同于執(zhí)行npx webpack

附件

webpack.config.js文件代碼:

const path = require('path');
const webpack = require('webpack')
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
    entry: {
        app: './src/index.js'
    },
    mode: "development",//production
    devtool: 'cheap-module-eval-source-map',  //調(diào)試版本建議用
    plugins: [
        new CleanWebpackPlugin(),
        new webpack.HotModuleReplacementPlugin(),//熱更新
        new HtmlWebpackPlugin({
            template: "./src/index.html"
        }),
        new webpack.ProvidePlugin({
            jQuery: "jquery",
            $: "jquery"
        })
    ],
    module: {
        rules: [
            {
                test: /\.js$/,
                exclude: /node_modules/,
                loader: "babel-loader",
                options: {
                    "presets": [
                        ["@babel/preset-env", {
                            "targets": {
                                "chrome": "67"
                            },
                            "useBuiltIns": "usage"
                        }]
                    ]
                }
            },
            {
                test: /\.(png|jpg|gif)$/, use: {
                    loader: "url-loader",
                    options: {
                        name: 'images/[name].[ext]',
                        limit: 8192
                    }
                }
            },
            {
                test: /\.css$/, use: ["style-loader", "css-loader"]
            },
            {
                test: /\.scss$/, use: ["style-loader", "css-loader", "sass-loader", "postcss-loader"]
            }
        ],
    },
    output: {
        filename: '[name].bundle.js',
        path: path.resolve(__dirname, 'dist')
    },
    devServer: {
        contentBase: path.join(__dirname, "dist"),
        compress: true,
        open: true,
        port: 9000,
        hot:true,          //改了哪個(gè)文件诱鞠,就更新哪個(gè)文件挎挖,最小化更新,提交開(kāi)發(fā)效率航夺;
        hotOnly: true,  //啟用熱模塊替換蕉朵,而無(wú)需頁(yè)面刷新作為構(gòu)建失敗時(shí)的回退。
        proxy: {
            "/api": {
                target: "http://localhost:8081"http://dev環(huán)境設(shè)置代理阳掐,方便測(cè)試始衅;
            }
        }
    },

};

package.json代碼

{
  "name": "jquerytowebpack4",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "webpack-dev-server"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.10.4",
    "@babel/preset-env": "^7.10.4",
    "clean-webpack-plugin": "^3.0.0",
    "css-loader": "^3.6.0",
    "file-loader": "^6.0.0",
    "html-webpack-plugin": "^4.3.0",
    "postcss-loader": "^3.0.0",
    "sass-loader": "^9.0.2",
    "style-loader": "^1.2.1",
    "url-loader": "^4.1.0",
    "webpack": "^4.43.0",
    "webpack-cli": "^3.3.12",
    "webpack-dev-server": "^3.11.0"
  },
  "dependencies": {
    "babel-loader": "^8.1.0",
    "jquery": "^3.5.1"
  }
}

問(wèn)題匯總:

1冷蚂、安裝 xxx-loader成功后,打包報(bào)錯(cuò):this.getOption is not function
由于xxx-loader版本過(guò)高導(dǎo)致汛闸,降版本就行了蝙茶,可以看npm上的版本記錄,找前個(gè)版本的穩(wěn)定版诸老;

image.png

2隆夯、配置browserslist
node項(xiàng)目中不同位置設(shè)置browserslist對(duì)postcss-loader影響的權(quán)重
前端工程基礎(chǔ)知識(shí)點(diǎn)--Browserslist (基于官方文檔翻譯)

資料推薦
如何發(fā)布一個(gè)庫(kù)到npm倉(cāng)庫(kù)
webpack 中文文檔

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市别伏,隨后出現(xiàn)的幾起案子蹄衷,更是在濱河造成了極大的恐慌,老刑警劉巖厘肮,帶你破解...
    沈念sama閱讀 222,104評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件愧口,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡类茂,警方通過(guò)查閱死者的電腦和手機(jī)耍属,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)巩检,“玉大人厚骗,你說(shuō)我怎么就攤上這事〔杲恚” “怎么了溯捆?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,697評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)厦瓢。 經(jīng)常有香客問(wèn)我提揍,道長(zhǎng),這世上最難降的妖魔是什么煮仇? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,836評(píng)論 1 298
  • 正文 為了忘掉前任劳跃,我火速辦了婚禮,結(jié)果婚禮上浙垫,老公的妹妹穿的比我還像新娘刨仑。我一直安慰自己,他們只是感情好夹姥,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,851評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布杉武。 她就那樣靜靜地躺著,像睡著了一般辙售。 火紅的嫁衣襯著肌膚如雪轻抱。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,441評(píng)論 1 310
  • 那天旦部,我揣著相機(jī)與錄音祈搜,去河邊找鬼较店。 笑死,一個(gè)胖子當(dāng)著我的面吹牛容燕,可吹牛的內(nèi)容都是我干的梁呈。 我是一名探鬼主播,決...
    沈念sama閱讀 40,992評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼蘸秘,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼官卡!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起醋虏,我...
    開(kāi)封第一講書(shū)人閱讀 39,899評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤味抖,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后灰粮,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,457評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡忍坷,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,529評(píng)論 3 341
  • 正文 我和宋清朗相戀三年粘舟,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片佩研。...
    茶點(diǎn)故事閱讀 40,664評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡柑肴,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出旬薯,到底是詐尸還是另有隱情晰骑,我是刑警寧澤,帶...
    沈念sama閱讀 36,346評(píng)論 5 350
  • 正文 年R本政府宣布绊序,位于F島的核電站硕舆,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏骤公。R本人自食惡果不足惜抚官,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,025評(píng)論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望阶捆。 院中可真熱鬧凌节,春花似錦、人聲如沸洒试。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,511評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)垒棋。三九已至卒煞,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間捕犬,已是汗流浹背跷坝。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,611評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工酵镜, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人柴钻。 一個(gè)月前我還...
    沈念sama閱讀 49,081評(píng)論 3 377
  • 正文 我出身青樓淮韭,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親贴届。 傳聞我的和親對(duì)象是個(gè)殘疾皇子靠粪,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,675評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容