基于webpack手動(dòng)搭建一個(gè)簡(jiǎn)單的vue腳手架

前言

首先,當(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)目

初始目錄結(jié)構(gòu)

打包文件

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);

此時(shí)目錄結(jié)構(gòu)

注意:我結(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文件”搔谴。

此時(shí)目錄結(jié)構(gòu)

(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)背景圖片不見了

小于limit設(shè)定值

大于limit設(shè)定值生成圖片

大于limit設(shè)定值頁面引用圖片

所以這時(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/'
  }
...
}
添加publicPath屬性打包運(yùn)行后

好了,現(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"]
}

大功告成苛坚,圓滿收工比被!


此時(shí)目錄結(jié)構(gòu)

使用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)一看,一串紅哑蔫,很煩钉寝。

vue打包運(yùn)行報(bào)錯(cuò)

好吧弧呐,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 vueel屬性通常掛載的"#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了疙筹,只剩下使用一些配置插件了富俄。


此時(shí)目錄結(jié)構(gòu)

插件的使用

如果說loader是webpack的識(shí)別器的話禁炒,那么插件(plugin)就可以說是webpack的拓展器,幫助我們延伸webpack的功能

html-webpack-plugin插件

當(dāng)封裝之后霍比,發(fā)現(xiàn)我們webpack打包之后并沒有生成index.html文件幕袱,而我們需要生成html文件,所以應(yīng)該安裝html-webpack-plugin插件悠瞬。

  1. html-webpack-plugin插件 可以幫我們?cè)诖虬募蒱tml文件 并且自動(dòng)生成script標(biāo)簽引入我們打包的js文件
  2. 并且會(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)
    })
  ]
 ...
}

配置此插件后就可以將其中outputpublicPath屬性注釋或刪除浅妆,并且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插件劳秋。


vue的版權(quán)聲明

在國外,對(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)配置文件
    此時(shí)目錄結(jié)構(gòu)

    新增文件之后
  1. webpack.config.js中的代碼復(fù)制到base.config.js
  2. webpack.config.js中開發(fā)需要的配置抽取到dev.config.js
  3. webpack.config.js中開發(fā)需要的配置抽取到prod.config.js
  4. 刪除base.config.js中和dev.config.js 先巴、prod.config.js文件重復(fù)的代碼
  5. 刪除webpack.config.js其爵,也可以改個(gè)名讓webpack不認(rèn)識(shí)它冒冬,像我就改成webpack.config copy.js
  6. 安裝npm i webpack-merge -D伸蚯,幫助我們將不同環(huán)境中的配置和通用配置文件合并
  7. 修改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腳手架就干完了简烤!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末剂邮,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子横侦,更是在濱河造成了極大的恐慌挥萌,老刑警劉巖绰姻,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異引瀑,居然都是意外死亡狂芋,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門憨栽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來帜矾,“玉大人,你說我怎么就攤上這事屑柔÷庞” “怎么了?”我有些...
    開封第一講書人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵掸宛,是天一觀的道長(zhǎng)死陆。 經(jīng)常有香客問我,道長(zhǎng)唧瘾,這世上最難降的妖魔是什么措译? 我笑而不...
    開封第一講書人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮饰序,結(jié)果婚禮上瞳遍,老公的妹妹穿的比我還像新娘。我一直安慰自己菌羽,他們只是感情好掠械,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著注祖,像睡著了一般猾蒂。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上是晨,一...
    開封第一講書人閱讀 49,007評(píng)論 1 284
  • 那天肚菠,我揣著相機(jī)與錄音,去河邊找鬼罩缴。 笑死蚊逢,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的箫章。 我是一名探鬼主播烙荷,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼檬寂!你這毒婦竟也來了终抽?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎昼伴,沒想到半個(gè)月后匾旭,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡圃郊,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年价涝,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片持舆。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡飒泻,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出吏廉,到底是詐尸還是另有隱情泞遗,我是刑警寧澤,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布席覆,位于F島的核電站史辙,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏佩伤。R本人自食惡果不足惜聊倔,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望生巡。 院中可真熱鬧耙蔑,春花似錦、人聲如沸孤荣。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽盐股。三九已至钱豁,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間疯汁,已是汗流浹背牲尺。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留幌蚊,地道東北人谤碳。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像溢豆,于是被迫代替她去往敵國和親蜒简。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345