前言
首先,當(dāng)我們編寫代碼時(shí)船老,不通過模塊化的思想想要引入一個(gè)js,通常是在html文件中創(chuàng)建一個(gè)script標(biāo)簽滚躯,引入我們需要的js雏门,如果我們引入的是自己手寫的js,很容易發(fā)生變量重名的沖突掸掏。
例如:
// 變量同名沖突
// a.js
var a = 111 或者 let a = 111
// b.js
var a = 222 或者 let a = 222
// index.html 中同時(shí)引入a.js茁影、b.js發(fā)生錯(cuò)誤
所以,我們有時(shí)想通過一些方法去避免這些錯(cuò)誤,比如:匿名函數(shù)丧凤,但匿名函數(shù)又會(huì)發(fā)生每個(gè)js文件中的作用域私有募闲,而代碼不可發(fā)生復(fù)用的問題,因此又需要想方法解決愿待,例如:
// a.js
var moudleA = (function() {
const obj = {}
const a = 111
obj.a = a
return obj // 將匿名函數(shù)中的變量暴露出去浩螺,實(shí)現(xiàn)代碼復(fù)用
})()
// b.js
(function() {
const a = 111
console.log(moudleA.a) // 引用a中的變量,并且解決變量重名
})()
// index.html 中同時(shí)引入a.js、b.js
并且仍侥,這種導(dǎo)入方式對(duì)js插入順序依賴性很強(qiáng)要出,一般公司多人開發(fā),不同的開發(fā)人員引入不同的js文件农渊,插入位置錯(cuò)誤發(fā)生的報(bào)錯(cuò)患蹂。
但不可否認(rèn),通過匿名函數(shù)將變量暴露出去這種方式砸紊,就是最基礎(chǔ)的模塊封裝传于。當(dāng)然現(xiàn)在對(duì)于前端模塊化已經(jīng)有了很多規(guī)范:Common.js、AMD醉顽、CMD沼溜、ES6中的Modules。
當(dāng)然徽鼎,這些東西我這不進(jìn)行說明了盛末,資料百度就行。
開始
1. 先創(chuàng)建一個(gè)項(xiàng)目
打包文件
2.安裝和使用webpack
使用模塊化思想否淤,解決變量重名和代碼打包
當(dāng)然開發(fā)文件中需要安裝依賴和包, 先將文件夾init一下吧悄但。
npm init -y
文件夾是中文名的話,這樣會(huì)報(bào)錯(cuò)石抡,需要npm init
回車然后填寫名稱檐嚣,其他信息一路回車即可,然后熟悉的package.json
兩兄弟文件就在根目錄中出來了。
現(xiàn)在安裝webpack,我使用的是3.6.0, 現(xiàn)在版本4.4.x了嚎京,你想跟我一樣 直接npm i webpack@3.6.0 -D
即可嗡贺。
我npm安裝是縮寫模式, 簡(jiǎn)單說下:
-D
為 --save-dev
開發(fā)環(huán)境中使用
-S
為 --save
生成環(huán)境中使用
縮寫不縮寫無所謂, 不差那幾個(gè)字母, 我比較懶。
順帶說下為啥在項(xiàng)目中安裝webpack鞍帝,而不是全局安裝?
當(dāng)你全局安裝了webpack, 你使用指令
webpack
打包又先調(diào)用的是你全局的webpack诫睬。 畢竟你今天安裝的webpack是這個(gè)版本,不能保證以后誰拿你代碼一運(yùn)行調(diào)用他電腦下載的webpack版本帕涌,beng摄凡,滿屏飄紅就出來了。
所以保險(xiǎn)點(diǎn)蚓曼,項(xiàng)目都安裝自己的webpack亲澡。
2.1 打包
當(dāng)你安裝好webpack后執(zhí)行打包指令后, 執(zhí)行"webpack xxxx"時(shí)要注意,此時(shí)如果你安裝了全局webpack纫版,任然調(diào)用的是你全局的而不是項(xiàng)目自己的床绪,你項(xiàng)目調(diào)用自己的webpack指令應(yīng)該是./node_modules/.bin/webpack xxxxx
這時(shí)你會(huì)說 “我@#$X,很@#%煩”, 為了解決該問題其弊,我們可以添加webpack.config.js
// webpack.config.js
const path = require("path")
module.exports = {
entry: "./main.js", // 入口
output: {
path: path.resolve(__dirname, 'dist'), // 出口癞己。必須為絕對(duì)路徑,所以借助node的path模塊
filename: 'bundle.js' // 打包后文件名
},
}
// 意思就是:我根目錄有個(gè)main.js文件梭伐,里面導(dǎo)入了好多東西末秃,幫我打包到我目錄里面的dist文件下bundle.js文件里
并且還需要更改一下pachage.json文件中的scripts屬性
{
...
scripts: {
...
"build": "webpack" // build可以隨便取,如: 叫xxx,終端運(yùn)行 npm run xxx即可
}
...
}
// 意思: 以后我直接在終端運(yùn)行一個(gè)叫build的指令去調(diào)用webpack打包, 并且通過該指令, 會(huì)自動(dòng)幫我們調(diào)用開發(fā)環(huán)境中的webpack打包
當(dāng)運(yùn)行npm run build
時(shí)籽御,webpack會(huì)看看我們根目錄是不是有一個(gè)叫webpack.config.js的文件练慕,然后讀取運(yùn)行其中的配置。
弄完這一步技掏,最后將index.html
中引入的main.js
改為bundle.js
后铃将,我們可以愉快的將各個(gè)js文件當(dāng)成模塊,各種require哑梳、import劲阎、、鸠真、,盡情導(dǎo)入導(dǎo)出的去騷了悯仙。
比如,我這里在src文件夾中新建js
文件夾吠卷,添加info.js
锡垄、mainUnit.js
然后再main.js
中引入并使用
// info.js
const name = "zou";
const age = 18;
const height = 18.8;
export default {
name,
age,
height
}
// mainUnit.js
function add(num1, num2) {
return num1 + num2
}
function mul(num1, num2) {
return num1 * num2
}
module.exports = {
add,
mul
}
// main.js
import info from './src/js/info';
const {add, mul} = require('./src/js/mainUnit.js');
console.log(add(100, 200));
console.log(mul(100, 200));
console.log(info);
注意:我結(jié)構(gòu)中webpack.config.js多了copy是因?yàn)楹笃谧隽顺殡x,webpack打包并沒有調(diào)用我的webpack.config copy.js
loader的使用
webpack并不能識(shí)別許多文件類型祭隔,我們需要通過各種各樣的loader货岭,來幫webpack識(shí)別。
干完上面一步的時(shí)候, 在我們騷的還沒盡興完時(shí)。
領(lǐng)導(dǎo)一看千贯,“我靠屯仗,流批,給我把所有的js相關(guān),css相關(guān),圖片相關(guān)都給我弄進(jìn)去, 以后我只上線你導(dǎo)出的這一個(gè)js文件”搔谴。
(css隨便添加點(diǎn)東西魁袜,less文件中寫些less語法)
這時(shí),在main.js中引入
require("xxx.css")
或者import "xxx.less"
敦第,然后一運(yùn)行慌核,發(fā)現(xiàn)我的終端,好紅啊申尼。
3.1引入css相關(guān)loader
進(jìn)入webpack官網(wǎng), 點(diǎn)擊導(dǎo)航中的LOADERS,點(diǎn)擊左邊導(dǎo)航的樣式垫桂,然后就可以根據(jù)需求對(duì)照文檔安裝和配置你需要的樣式相關(guān)loader了
我這里安裝css和less相關(guān)的loader师幕,npm i style-loader css-loader less-loader less -D
因?yàn)閘oader基本用于開發(fā)環(huán)境, 所以安裝一般都為--save-dev
// webpack.config.js
module.exports = {
...
rules: [
{
test: /\.css$/,
// css-loader 只負(fù)責(zé)解析css,并不負(fù)責(zé)插入樣式到頁面
// style-loader 負(fù)責(zé)將樣式插入頁面中
// 使用多個(gè)loader時(shí)诬滩,從右往左調(diào)用
use: ['style-loader','css-loader']
},
{
test: /\.less$/,
use: [{ // use中如需配置其他options 可以使用Object形式霹粥, 否則不配置可直接用Array形式,同上css-loader
loader: "style-loader"
}, {
loader: "css-loader"
}, {
loader: "less-loader"
}]
},
]
...
}
好了疼鸟,css文件的問題解決了后控,現(xiàn)在繼續(xù)解決圖片的問題
3.2引入img相關(guān)loader
在網(wǎng)上隨便找2張一大一小圖片,隨便一個(gè)引入的css文件中添加空镜,我是在less中添加浩淘,順便試一試less-loader,如:
@fontSize: 40px;
@fontColor: orange;
body {
//font-size: @fontSize;
//color: @fontColor;
background-image: url('../img/big.jpg');
background-size: 30%;
}
同樣進(jìn)入webpack官網(wǎng), 點(diǎn)擊導(dǎo)航中的LOADERS吴攒,找找找张抄,蒙了!沒有img相關(guān)的loader啊洼怔。那我來告訴你署惯,去看看文件類目中的url-loader
。
話不多說镣隶,對(duì)著文檔就是一頓安裝极谊,復(fù)制
// webpack.config.js
module.exports = {
...
rules: [
...
{
test: /\.(png|jpg|gif)$/,
use: [{
loader: 'url-loader',
options: {
// 當(dāng)加載圖片,小于limit時(shí)安岂,會(huì)將圖片編譯成base64字符串形式
// 當(dāng)加載圖片查坪,大于limit時(shí)蚌成,需要安裝file-loader進(jìn)行加載,加載圖片會(huì)放入你打包輸出的文件目錄
limit: 8192 // 8192 / 1024 = xKB
}
}]
}
...
]
...
}
limit屬性說明如上方注釋,當(dāng)圖片小于limit設(shè)定的值時(shí)以base64字符串形式插入在打包的js中赫粥,此時(shí)沒問題赘阀。
但是,一旦大于設(shè)定值,webpack會(huì)報(bào)錯(cuò)友瘤,需要安裝file-loader
,安裝即可檐束,不需要單獨(dú)配置辫秧。
然后wenpack會(huì)將引入圖片完整打包放入dist
文件夾目錄下,名稱為32位hash值被丧,并將開發(fā)環(huán)境中引用的圖片路徑替換為打包生成的圖片盟戏,而此時(shí)index.html引用的為開發(fā)目錄中(即img文件夾下)的圖片,所以打包后再運(yùn)行index.html
發(fā)現(xiàn)背景圖片不見了
所以這時(shí)我們需要當(dāng)圖片大于limit設(shè)定值時(shí)的打包后頁面引入路徑更改為
dist/xxxxx
甥桂,好的柿究,進(jìn)入webpack.config.js,在其中output
屬性中添加publicPath
屬性
// webpack.config.js
module.exports = {
...
output: {
...
// 添加該屬性黄选,以后打包文件所有涉及到url的東西蝇摸,都會(huì)自動(dòng)在路徑前添加 dist/
publicPath: 'dist/'
}
...
}
好了,現(xiàn)在js模塊办陷、css相關(guān)貌夕、圖片相關(guān)都可以正常被打包了。
我們通常并不希望民镜,所有的img全部打包在dist文件夾下啡专,而是希望放在dist/img文件夾中,并且希望圖片保持原名制圈,但怕重名们童,還需要加點(diǎn)hash值。
因此鲸鹦,我們可以繼續(xù)配置url-loader
規(guī)則
// webpack.config.js
module.exports = {
...
rules: [
...
{
test: /\.(png|jpg|gif)$/,
use: [{
loader: 'url-loader',
options: {
limit: 8192 ,
// 當(dāng)不希望它打包直接放入dist文件中時(shí)病附,可以添加name屬性,
// 當(dāng)需要保存原名時(shí)可以添加[name]
// 當(dāng)需要防止重名又不需要太長(zhǎng)的hash值時(shí)可以添加[hash: x] x為你需要hash值位數(shù)
name: 'img/[name].[hash:8].[ext]'
}
}]
}
...
]
...
}
好了亥鬓,打包試試看完沪。
因?yàn)橹坝?code>publicPath配置,所以打包運(yùn)行index.html
頁面圖片引入路徑仍然為dist/img/xxxx.xxx
ES6轉(zhuǎn)ES5
完成上面一步之后嵌戈,領(lǐng)導(dǎo)打開他很久沒更新的瀏覽器覆积,發(fā)現(xiàn)頁面并沒有出來,打開控制臺(tái)一看熟呛,全是ES6語法報(bào)錯(cuò)宽档,然后立馬說:“你這打包不對(duì)勁啊,瀏覽器版本一低就各種報(bào)錯(cuò)庵朝,我們不能保證用戶都使用可以識(shí)別ES6語法的瀏覽器吗冤,代碼應(yīng)該要將老舊瀏覽器都兼容啊又厉。”
好吧椎瘟,滿足他的需求覆致,打開瀏覽器搜索babel
,進(jìn)入中文官網(wǎng)肺蔚,點(diǎn)擊設(shè)置
選擇Webpack
煌妈,對(duì)照文檔在編輯器中一頓輸出。
npm install --save-dev babel-loader @babel/core @babel/preset-env
安裝完成后宣羊,在webpack.config.js中添加規(guī)則:
// webpack.config.js
module.exports = {
...
rules: [
...
{
test: /\.js$/,
exclude: /node_modules/, // 排除的目錄
// 使用babel-loader將ES6代碼轉(zhuǎn)為ES5璧诵,做瀏覽器兼容
// 同時(shí)需要建立.babelrc文件,調(diào)用@babel/preset-env插件將E6轉(zhuǎn)為E5S
loader: "babel-loader"
}
...
]
...
}
此時(shí)仇冯,babel-loader
已經(jīng)可以將ES6語法識(shí)別之宿,但是打包將ES6轉(zhuǎn)ES5還需要@babel/preset-env
插件,所以我們要新建一個(gè)名為.babelrc
的babel配置文件使用該轉(zhuǎn)譯插件:
// .babelrc
{
"presets": ["@babel/preset-env"]
}
大功告成苛坚,圓滿收工比被!
使用Vue
正準(zhǔn)備執(zhí)行回家程序操作,領(lǐng)導(dǎo)叫住說:“項(xiàng)目前端框架要用vue炕婶,就用你那玩意搞,正好可以打包莱预∧啵”得,繼續(xù)搭vue吧依沮。
npm i vue -S
因?yàn)関ue不僅是在開發(fā)環(huán)境中使用涯贞,并且打包后依然需要依賴vue,所有安裝在生成環(huán)境中危喉。
安裝之后宋渔,在main.js
中使用一下吧
// main.js
import Vue from "vue";
new Vue({
el: "#app",
data: {
msg: "哈哈辜限,使用了Vue"
}
})
然后在index.html
中使用一下
// index.html
...
<div id="app">
<h2>{{ msg }}</h2>
</div>
...
寫完后皇拣,覺得干的很漂亮,美滋滋薄嫡,打包氧急,運(yùn)行index.html
,dang毫深,在頁面上沒有看到哈哈吩坝,打開控制臺(tái)一看,一串紅哑蔫,很煩钉寝。
好吧弧呐,
main.js
中引入的vue模塊,使用的是runtime-only
版本的嵌纲,該版本有vue運(yùn)行代碼俘枫,但沒有編譯template
的代碼。那咋辦疹瘦,換個(gè)vue模塊引入的版本唄崩哩,打開webpack.config.js。
// webpack.config.js
module.exports = {
...
// 設(shè)置模塊如何被解析
resolve: {
// 當(dāng)安裝vue時(shí)言沐,默認(rèn)使用的是runtime-only版本邓嘹,此版本只含有vue運(yùn)行的代碼,不包含編譯template的代碼
// 需要重新更換含有runtime-compiler的版本险胰,因?yàn)閞untime-complier含有complier代碼可以用于編譯template
// alias(別名): 用別名代替前面的路徑汹押,不是省略,而是用別名代替前面的長(zhǎng)路徑
// 如下起便,當(dāng)main.js中import Vue from "vue"時(shí)棚贾,因?yàn)関ue是別名,所以實(shí)際為import Vue from "vue/dist/vue.esm.js"
// 別名好處是webpack直接會(huì)去別名對(duì)應(yīng)的目錄去查找模塊榆综,減少了webpack自己去按目錄查找模塊的時(shí)間
alias: {
'vue$': 'vue/dist/vue.esm.js'
}
},
...
}
屬性解釋如上圖妙痹,語文好的去官方文檔看,反正我是理解不了它說的啥鼻疮,文檔說點(diǎn)白話怯伊,通俗易懂不好嗎。
簡(jiǎn)單說alias
就是拼接導(dǎo)入模塊的路徑判沟,emmm耿芹,還是舉例吧,如下:
// webpack.config.js
...
alias: {
'vue$': 'vue/dist/vue.esm.js' // 這是別名vue
}
...
// main.js
import Vue from "vue" <==> import Vue from "vue/dist/vue.esm.js"
import Vue from "vue/xxx/xxx" <==> import Vue from "vue/dist/vue.esm.js/xxx/xxx"
好了挪哄,應(yīng)該懂了吧秕,反正也是寫我自己看的,你們不理解百度去吧迹炼。
在我這其實(shí)是將alias
當(dāng)成vue模塊引入版本重定向砸彬,當(dāng)引入vue,默認(rèn)引入vue.runtime.common.js文件斯入,而我將引入文件重定向?yàn)関ue.esm.js拿霉。
我怎么知道默認(rèn)引入哪個(gè)版本的?
打開node_modules/vue/package.json咱扣,查看其中main屬性绽淘,就是vue模塊默認(rèn)引入的版本。
其他版本闹伪,在node_modules/vue/dist文件夾中沪铭。
到這一步壮池,vue配置就完成了。
vue中template的封裝
完成上一步已經(jīng)可以打包運(yùn)行vue杀怠,并且編譯template語法了椰憋。上方?jīng)]重定向之前,明明沒有template語法為何打包運(yùn)行會(huì)報(bào)錯(cuò)呢赔退?
// vue中template語法之一
// html
...
<div id="app"></div>
<template id="demo">
<div>
這是模板語法之一
</div>
</template>
...
// js
const tmp = {
template: "#demo"
}
Vue.component("cpn", tmp)
是不是感覺很熟悉橙依?可以理解為new vue
中el
屬性通常掛載的"#app"
其實(shí)就是實(shí)例的模板。
好了硕旗,回歸當(dāng)前正題窗骑,一般在使用vue開發(fā)過程中,我們會(huì)發(fā)現(xiàn)通常只有一個(gè)html文件漆枚,稱之為單頁面復(fù)應(yīng)用(SPA:single-page application)创译,而在SPA中,我們不希望所有的節(jié)點(diǎn)全部寫在那一個(gè)html文件,html中只需要一個(gè)vue掛載節(jié)點(diǎn)即可墙基,并且也不希望將所有的js全部寫在new Vue
中软族,所以需要將代碼進(jìn)一步的封裝。
下面展示残制,如何將代碼一步一步抽離:
1. 初始代碼
// index.html
...
<div id="app">
{{ msg }}
<button @click="btnClick">點(diǎn)擊</button>
</div>
...
// main.js
...
new Vue({
el: "#app",
data: {
msg: "哈哈立砸,使用了Vue"
},
methods: {
btnClick() {
console.log('vue內(nèi)容封裝');
}
}
})
...
1.1封裝一
// index.html
...
<div id="app"></div>
...
// main.js
...
new Vue({
el: "#app",
template: `
<div id="app">
{{ msg }}
<button @click="btnClick">點(diǎn)擊</button>
</div>
`,
data: {
msg: "哈哈,使用了Vue"
},
methods: {
btnClick() {
console.log('vue內(nèi)容封裝');
}
}
})
...
1.2封裝二
// main.js
...
new Vue({
el: "#app",
template: '<App/>',
components: {
App: {
template: `
<div id="app">
{{ msg }}
<button @click="btnClick">點(diǎn)擊</button>
</div>
`,
data() {
return {
msg: "哈哈初茶,使用了Vue"
}
},
methods: {
btnClick() {
console.log('vue內(nèi)容封裝');
}
}
}
}
})
...
1.3封裝三
利用模板化思想颗祝,將組件抽離放入一個(gè)js文件中,將其暴露出來纺蛆,在src文件夾新建vue文件夾中新建app.js
// app.js
export default {
template: `
<div id="app">
{{ msg }}
<button @click="btnClick">點(diǎn)擊</button>
</div>
`,
data() {
return {
msg: "哈哈吐葵,使用了Vue"
}
},
methods: {
btnClick() {
console.log('vue內(nèi)容封裝');
}
}
}
// main.js
import App from './src/vue/app.js';
new Vue({
el: "#app",
template: '<App/>',
components: {
App
}
})
做完這一步规揪,項(xiàng)目已經(jīng)實(shí)現(xiàn)模塊化思想桥氏,但是此時(shí)封裝缺點(diǎn)是模板(即節(jié)點(diǎn))沒有和js分離,這時(shí)候需要使用.vue
文件做進(jìn)一步封裝
1.4封裝四
在vue文件夾中創(chuàng)建App.vue猛铅,刪除app.js(也可以保留字支,只有main.js里沒引用就行)
// App.vue
<template>
<div id="app">
{{ msg }}
{{ devServer }}
<button @click="btnClick">點(diǎn)擊</button>
</div>
</template>
<script>
export default {
name: "App",
data() {
return {
msg: 'hello Webpack!',
devServer: '測(cè)試webpack-dev-server插件是否生效'
}
},
methods: {
btnClick() {
console.log('vue內(nèi)容封裝--App.vue');
}
}
}
</script>
<style lang="scss" scoped>
</style>
將main.js中導(dǎo)入app.js修改成導(dǎo)入App.vue
// main.js
// import App from './src/vue/app.js';
import App from './src/vue/App.vue';
此時(shí),打包項(xiàng)目奸忽,發(fā)現(xiàn)終端報(bào)錯(cuò)堕伪,因?yàn)閣ebpack并不能識(shí)別.vue
文件,所以需要安裝對(duì)應(yīng)的loader
來幫助webpack識(shí)別.vue
文件栗菜。
npm i vue-loader vue-template-compiler -D
在webpack.config.js中配置loader規(guī)則:
// webpack.config.js
const VueLoaderPlugin = require('vue-loader/lib/plugin');
module.exports = {
...
module: {
rules: [
...
{
test: /\.vue$/,
loader: 'vue-loader'
}
...
]
},
plugins: [
new VueLoaderPlugin() // 因?yàn)槲野惭b的"vue-loader"版本為"^15.7.2",需要配置此插件
]
}
...
做到這里欠雌,到時(shí)候,是不是發(fā)現(xiàn)已經(jīng)很像vue-cli了疙筹,只剩下使用一些配置插件了富俄。
插件的使用
如果說loader是webpack的識(shí)別器的話禁炒,那么插件(plugin)就可以說是webpack的拓展器,幫助我們延伸webpack的功能
html-webpack-plugin插件
當(dāng)封裝之后霍比,發(fā)現(xiàn)我們webpack打包之后并沒有生成index.html文件幕袱,而我們需要生成html文件,所以應(yīng)該安裝html-webpack-plugin插件悠瞬。
- html-webpack-plugin插件 可以幫我們?cè)诖虬募蒱tml文件 并且自動(dòng)生成script標(biāo)簽引入我們打包的js文件
- 并且會(huì)將頁面所有引入的相關(guān)鏈接自動(dòng)指向輸出的文件夾目錄下問生成文件
先來安裝該插件npm i html-webpack-plugin -D
们豌,然后再到webpack.config.js中繼續(xù)配置
// webpack.config.js
...
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
...
output: {
...
// publicPath: 'dist/'
},
plugins: [
...
new HtmlWebpackPlugin({
template: 'index.html' // 指定生成html的模板,如果不知道只會(huì)默認(rèn)生成html文件插入打包后js,并沒有<div di="app"></div>節(jié)點(diǎn)
})
]
...
}
配置此插件后就可以將其中output
的publicPath
屬性注釋或刪除浅妆,并且index.html
中script標(biāo)簽引入bundle.js
這段也可以刪除了望迎。
uglifyjs-webpack-plugin插件
這個(gè)插件可以幫助我們壓縮和丑化打包的js代碼,當(dāng)然js壓縮不壓縮看自己需求狂打。
為什么不直接用webpack打包是因?yàn)関ue-cli2中使用該插件打包并沒有使用webpack自帶的打包擂煞,安裝此插件版本不用安裝最新,這里只做演示所以安裝的為1.1.1版本趴乡,安裝最新版本會(huì)報(bào)錯(cuò)对省,需要重新查看使用文檔。
先安裝晾捏,npm i uglifyjs-webpack-plugin@1.1.1 -D
蒿涎,然后到webpack.config.js中配置
// webpack.config.js
...
const UglifyjsWebpackPlugin = require('uglifyjs-webpack-plugin');
module.exports = {
...
plugins: [
...
new UglifyjsWebpackPlugin(), // 壓縮 丑化打包后的js
]
...
}
BannerPlugin插件
當(dāng)時(shí)需要對(duì)打包文件添加版權(quán)聲明時(shí)(當(dāng)然對(duì)我們國家來說,你開源的就是大家的)惦辛,可以使用webpack自帶的BannerPlugin插件劳秋。
在國外,對(duì)版權(quán)還是很重視的胖齐,所以大公司開源的代碼大多攜帶版權(quán)聲明玻淑,和版權(quán)協(xié)議類型。
其中vue使用的是MIT協(xié)議呀伙,此協(xié)議代表作者只想保留版權(quán)补履,而無任何其他了限制。
曾經(jīng)的react的協(xié)議并不是MIT而是BSD剿另,該協(xié)議就是說箫锤,如果你公司以react為核心構(gòu)建了項(xiàng)目,當(dāng)有一天Facebook(react是Facebook的)公司要對(duì)你公司干點(diǎn)什么的話雨女,比如下架產(chǎn)品谚攒,或者收費(fèi)什么的,那你公司就麻煩了氛堕,具體自己可以百度查查馏臭,所以當(dāng)初很多公司項(xiàng)目開始想用react但看到協(xié)議都放棄了,比如:百度讼稚。
題外話不好了括儒,來使用一波BannerPlugin
// webpack.config.js
...
const webpack = require('webpack');
module.exports = {
...
plugins: [
...
new webpack.BannerPlugin('這是在js壓縮后添加的版權(quán)聲明')
]
...
}
注意:如果同時(shí)使用了uglifyjs-webpack-plugin和BannerPlugin浪耘,將uglifyjs-webpack-plugin放在BannerPlugin之前調(diào)用,防止把你的聲明也給丑化了塑崖,那要聲明干嘛七冲。
webpack-dev-server(熱更新)
webpack提供一個(gè)可選本地開發(fā)服務(wù)器,這個(gè)本地服務(wù)器基于node.js搭建规婆,內(nèi)部使用express框架澜躺,可以實(shí)現(xiàn)讓瀏覽器自動(dòng)刷新顯示我們修改后的結(jié)果
弄完上面那些東西,是不是覺得每次修改代碼都需要打包再運(yùn)行很煩抒蚜,現(xiàn)在掘鄙,它(熱更新)來了。
先安裝npm i webpack-dev-server -D
嗡髓,老規(guī)矩操漠,在webpack.config.js中配置
// webpack.config.js
...
module.exports = {
...
output: {...},
devServer: {
contentBase: './dist', // 為哪一個(gè)文件夾提供服務(wù),默認(rèn)根目錄
inline: true // 頁面實(shí)時(shí)刷新
// port: 8080, // 端口號(hào)饿这,默認(rèn)8080
// 其他配置自行看文檔
},
...
}
想要使用它浊伙,還需要修改項(xiàng)目中的package.json,在其script
屬性中添加運(yùn)行指令(也可以不加长捧,直接在終端寫路徑去調(diào)用嚣鄙,同之前webpack調(diào)用)
// package.json
...
"scripts": {
"dev": "webpack-dev-server"
}
...
然后,在終端中運(yùn)行指令npm run dev
串结,之后就可以實(shí)時(shí)查看修改代碼而不用頻繁去打包運(yùn)行了哑子。
webpack.config.js抽離 和 webpack-merge
在我們安裝的依賴當(dāng)中,有些是開發(fā)和生產(chǎn)時(shí)需要的依賴肌割,有些是開發(fā)時(shí)的依賴卧蜓,還有些是生產(chǎn)時(shí)的依賴,我們不希望每次都運(yùn)行所有的依賴把敞,所以需要對(duì)webpack.config.js進(jìn)行抽離封裝
在根目錄新建build
文件夾弥奸,新增三個(gè)js文件,如下:
-
base.config.js
為通用配置文件 -
dev.config.js
為開發(fā)配置文件 -
prod.config.js
為生產(chǎn)配置文件
新增文件之后
- 將
webpack.config.js
中的代碼復(fù)制到base.config.js
中 - 將
webpack.config.js
中開發(fā)需要的配置抽取到dev.config.js
中 - 將
webpack.config.js
中開發(fā)需要的配置抽取到prod.config.js
中 - 刪除
base.config.js
中和dev.config.js
先巴、prod.config.js
文件重復(fù)的代碼 - 刪除
webpack.config.js
其爵,也可以改個(gè)名讓webpack不認(rèn)識(shí)它冒冬,像我就改成webpack.config copy.js
- 安裝
npm i webpack-merge -D
伸蚯,幫助我們將不同環(huán)境中的配置和通用配置文件合并 - 修改
package.json
指令
// dev.config.js
const webpackBase = require("webpack-merge"); // 合并模板
const baseConfig = require("./base.config"); // 導(dǎo)入共同配置
module.exports = webpackBase(baseConfig, {
devServer: {
contentBase: '../dist',
inline: true
}
})
// prod.config.js
// 開發(fā)調(diào)試時(shí)需要將 共同配置合并開發(fā)配置
const webpackBase = require("webpack-merge"); // 合并模板
const baseConfig = require("./base.config"); // 導(dǎo)入共同配置
const UglifyjsWebpackPlugin = require('uglifyjs-webpack-plugin');
const webpack = require('webpack');
module.exports = webpackBase(baseConfig, {
plugins: [
new UglifyjsWebpackPlugin(),
new webpack.BannerPlugin('這是在js壓縮后添加的版權(quán)聲明')
]
})
// base.config.js 復(fù)制webpack.config.js代碼并刪除以上配置
// package.json
...
"scripts": {
"build": "webpack --config ./build/prod.config.js",
"dev": "webpack-dev-server --config ./build/dev.config.js"
}
...
自此,一個(gè)簡(jiǎn)單的vue腳手架就干完了简烤!