使用 webpack 搭建 vue 開發環境
本篇筆記為學習網易公開課後做的筆記,課程是網易譚金龍老師講的, 地址:https://study.163.com/sl/VsaN
請勿直接爬走,本文地址:https://www.cnblogs.com/xiaoxuStudy/p/13492608.html
本篇筆記的內容不一定完全正確,因為我有的地方不懂,先把筆記做下來, 如果有錯誤的地方麻煩指出,謝謝。
目錄:
如果為了“開箱即用”,可以使用命令 vue create project 或 vue init webpack project 去建立 vue 專案, “開箱即用”是約定大於配置,簡單來說就是能不配置就不配置按照人家的方式來,作者不建議配置但是不會攔著我們去配置。但是如果想要成為一個高階前端工程師或架構師,最好要理解 vue-cli 的架構原理。
腳手架:主體結構全部搭建好了,我們可以在利用這個主體結構去完成我們的需求
vue-cli 不是一個單獨的東西,甚至它不是一個東西,它自己也沒有什麼特別的功能,它其實是 git 上的一個專案,或者說它就是一堆檔案,真正有功能的是 webpack。可以到 github 上看看,搜尋 webpack, 點選下圖這個進去看看
點 template 進去看看
下圖這個目錄就是使用命令 vue init webpack xxx 時下載的東西,使用的時候用命令 npm run start 去啟動這些東西
但是,現在使用的基本上都是 vue-cli3.x 或者 vue-cli4.x,vue-cli3.x 是基於 webpack4 打造的,vue-cli2.x 是基於 webpack3 打造的,webpack3 跟 webpack4 的區別挺大的,所以不建議全域性安裝 webpack
vue-cli3 學習了 rollup 的零配置思路,所以在專案初始化之後沒有以前的一些東西了,也找不到配置檔案了,這幫助開發者解決了絕大部分情形下的 webpack 配置,但是,我們還是很有必要去了解 webpack 的。
vue-cli 這個腳手架其實什麼都沒幹,其實,vue-cli 就是一個下載器,官方叫 vue-cli 啟動器,它的作用是幫助我們快速去建立一些基本專案,但是這個專案不是完全空白的,有些基本的東西,比如說可以根據選擇的專案的不同下載不同的依賴、根據我們的選擇更改專案名、可以選擇單元測試方法是單元測試還是一對一測試。
接著上面看 github 的東西,開啟 package.json 看看
可以看到 package.json 裡面有各種各樣的 loader,webpack 只能處理 js 檔案,webpack 不認識 vue,loader 的作用就是把 vue 檔案轉成 js 檔案,之後配置上 plugin 各種擴充套件功能。總結一下,webpack 中的 loader 是為了將 webpack 不認識的檔案轉成 js 檔案。各種 loader、plugin 為 webpack擴充套件功能,所以 vue-cli 沒有這麼了不起,真正牛逼的是 webpack。vye
瞭解 vue-cli 工作原理之後,可以利用 webpack 自己去搭建一個 vue 的開發環境。總而言之,vue-cli 是一個下載器,它從 git 上去下載一個目錄。
下面利用 webpack 去搭建去架構一個 vue 的開發環境,甚至可以說是自己去架構一個 vue-cli。
例子
首先新建一個資料夾,我新建了個 0812 資料夾,到該目錄下生成一個 package.json 工程管理檔案
命令: yarn init -y
因為要利用 webpack 去搭建去架構一個 vue 的開發環境,所以要把 webpack 拿下來。不建議全域性安裝 webpack。其中 webpack-cli 是一個簡易客戶端,用於與 webpack 協議連線,在 webpack3 裡它本身和客戶端是在同一個包裡的,但是在 webpack4 裡它們是分開的,所以在 webpack4 裡要通過命令 yarn add -D webpack webpack-cli 去下載 webpack,同時安裝 webpack-cli。
命令: yarn add -D webpack webpack-cli
新建一個 html 檔案
命令: touch index.html
新建一個 src 檔案
命令: mkdir src
在 src 目錄下新建一個 components
命令: mkdir components
使用 vscode 開啟檔案 0812
可以在 components 目錄下新建檔案,我這裡新建一個 xwh.js,然後編輯 xwh.js
可以從 vue/dist/vue.esm 引入 Vue,vue.esm 支援 es module 的 import...from 語句,所以引入這個。
(我後來執行程式碼時報錯了,上網搜尋後發現需要引入 vue,命令:npm i vue -S)
接著,新建一個 vm,傳入各種配置。註冊一個元件 components,區域性註冊一個 xwh 元件,在 data 裡 return 一個 msg,在 components 裡的寫 template 。在 components 外的 template 裡將元件 xwh 掛載起來。
import Vue from "vue/dist/vue.esm";
const vm = new Vue({
el: "#app",
data: {},
template: `
<div>
<xwh></xwh>
</div>
`,
components: {
xwh: {
data() {
return {
msg: "小許想要快點找到工作",
};
},
template: `
<div>
<h1>{{ msg }}</h1>
</div>
`,
},
},
});
xwh.js
在目錄 0812 下新建一個 webpack.config.js, webpack.config.js 是一個 webpack 的預設配置檔案。
在 webpack.config.js 裡面寫配置。首先,寫向外暴露的東西。
首先設定模式,mode 有 3 個值可選:development、production、none(可參考官網或網路資料,官網:https://webpack.js.org/configuration/mode/, 網路資料:https://blog.csdn.net/cuipp0509/article/details/105329735/),主要區別就是打包時壓縮跟不壓縮,development 對應的是開發環境,不需要壓縮,production 對應的是生產環境,需要壓縮,這裡設定為 none( 對應語句:mode:'none' )。
然後,要找入口,設定入口,入口就找 “./src/components/xwh.js” 這個路徑下的( 對應語句:entry:'./src/components/xwh.js')。
然後,要找出口,設定打包輸出的路徑,首先通過 node 裡面的 path 模組拿進來( 對應語句:constpath=require('path'); ),然後指定 path 跟 filename( 對應語句: output:{ path:path.resolve(__dirname,'dist'), filename:'bundle.js' } )。至此,基本寫好了一個 webpack 打包配置檔案。
const path = require('path');
module.exports = {
// 模式
mode:'none',
// 入口
entry:'./src/components/xwh.js',
// 打包輸出的路徑
output:{
path: path.resolve(__dirname, 'dist'),
filename:'bundle.js'
}
}
webpack.config.js
執行 webpack
命令: npx webpack
可以看到打包生成了一個目錄 dist 跟檔案 bundle.js
使用 bundle.js。開啟 index.js,引入 bundle.js
<!DOCTYPEhtml>
<htmllang="en">
<head>
<metacharset="UTF-8">
<metaname="viewport"content="width=d,initial-scale=1.0">
<title>Document</title>
</head>
<body>
<divid="app"></div>
<scriptsrc="./dist/bundle.js"></script>
</body>
</html>
index.html
頁面表現:
頁面顯示了 xwh.js 裡 msg 的值
現在把 msg 改一下,然後在瀏覽器重新整理頁面,會發現內容並沒有發生變化
改了之後需要重新打包,重新打包才可以發生改變。
每更新一次就需要重新打包一次,很麻煩。引入 webpack-dev-server 可以解決這個問題,webpack-dev-server 用於開發除錯,提供 web 服務,熱更新,介面代理等。
命令: yarn add -D webpack-dev-server
執行 webpack-dev-server
命令: npx webpack-dev-server
在 xwh.js 中更改 msg,重新整理頁面後發現仍然沒有實現實時更新。
之所以不能實時更新,是因為在 index.html 中引用 bundle.js 的路徑錯了,因為使用了 webpack-dev-server,所以路徑在根目錄下,修改路徑後重新整理頁面後就能實現實時更新了。
現在,只要直接更改 msg 就實現在頁面上實時更新。
在 xwh.js 中更改 msg,重新整理頁面後發現實現了實時更新。
webpack-dev-server 打包後的 js 檔案是在記憶體裡邊維護的,記憶體裡的檔案有一個問題:如果伺服器重啟,記憶體裡的資料就沒了。
所以,如果是部署在生產環境時使用 webpack-dev-server 的話會出問題,因為伺服器需要隔段時間進行重啟,一重啟記憶體裡的資料就沒了。
因此,在開發的時候,並不需要去生成檔案,只需要在記憶體裡維護一份。但是,在專案開發完畢之後,必須要生成檔案,如果記憶體裡維護一份,伺服器重啟之後記憶體裡的檔案就沒了。
所以,使用 webpack 搭建 vue 開發環境是,需要去區分到底現在是在開發還是生產。
在 0812 目錄下新建一個 config,在 config 下新建 webpack.development.js 跟 webpack.production.js。
編輯 webpack.development.js 跟 webpack.production.js
為了判斷是開發還是生產,下面需要修改 webpack.config.js。
webpack 可以進行命令列的環境配置,可以在命令列中傳入任何引數,這會在配置檔案中對映為對應的引數。向外暴露一個函式,引數為 env,這個 env 是可以接收傳入的值,如果沒有傳入引數則 env 為空物件。然後,設定入口檔案為 xwh.js 。然後,判斷傳入的 env,如果是 development,就 require webpack.development.js,否則 require webpack.production.js,拿到檔案要將它展開。
(擴充套件運算子的作用,網路資料:https://segmentfault.com/a/1190000016753384?utm_source=tag-newest)
const path = require('path');
module.exports = (env) => {
env = env || {};
return {
entry: "./src/components/xwh.js",
...env.development ? require('./config/webpack.development') : require('./config/webpack.production')
};
}
webpack.config.js
傳入引數 development
命令: npx webpack --env.development
傳入引數 production
命令: npx webpack --env.production
上面實現了在命令列傳入不同的引數呼叫不同的檔案,但是這樣不方便。可以在 package.json 裡進行更改,設定如果是 dev 的話,設定為 webpack-dev-server 傳入引數 env.development,如果是 build 的話,直接執行打包傳入引數 env.production。
{
"name": "0812",
"scripts": {
"dev": "webpack-dev-server --env.development --open",
"build": "webpack --env.production"
},
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"devDependencies": {
"webpack": "^4.44.1",
"webpack-cli": "^3.3.12",
"webpack-dev-server": "^3.11.0"
},
"dependencies": {
"vue": "^2.6.11"
}
}
package.json
執行 dev
命令: yarn dev
執行 build
命令: yarn build
實現了判斷是開發還是生產後,可以繼續編寫配置檔案 webpack.development.js 跟 webpack.production.js。
為了與 vue 的結構儘量相同,刪除之前生成的 dist 目錄。
module.exports = {
// 開發模式, 在記憶體裡維護, 不需要壓縮與生成檔案
mode:'development',
// 打包輸出的路徑
output:{
filename:'bundle.js',
},
};
webpack.development.js
const path = require('path');
module.exports = {
// 生產模式
mode:'production',
// 打包輸出的路徑
output:{
path: path.resolve(__dirname, '../build'),
filename:'bundle.min.js'
}
}
webpack.production.js
執行 dev
命令: yarn dev
執行 build,生成檔案
命令: yarn build
現在有一個問題,index.html 裡面的 src 是寫死的。生產時,打包後的引用的路徑應該是 <scriptsrc="./build/bundle.min.js"></script> ,開發時,引用的路徑應該是 <scriptsrc="/bundle.js"></script> 。每次都要手動去進行更改很麻煩。
解決的辦法是連 html 也一起打包了,需要引入外掛 html-webpack-plugin 。
首先,在 0812 資料夾下新建一個 public 目錄,將 index.html 移動到 public 目錄下。然後,將 index.html 裡引用檔案的語句刪掉。
引入外掛
命令: yarn add -D html-webpack-plugin
使用 html-webpack-plugin。在 webpack.development.js 裡 require 它。
const htmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
// 開發模式, 在記憶體裡維護, 不需要壓縮與生成檔案
mode:'development',
// 打包輸出的路徑
output:{
filename:'bundle.js',
},
plugins: [
new htmlWebpackPlugin({
//模板檔案
template: "public/index.html",
//檔名
filename: "index.html",
}),
],
};
webpack.development.js
在 webpack.production.js 裡 require 它。
const path = require('path');
const htmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
// 模式
mode:'production',
// 打包輸出的路徑
output:{
path: path.resolve(__dirname, '../build'),
filename:'bundle.min.js'
},
plugins: [
new htmlWebpackPlugin({
//模板檔案
template: "public/index.html",
//檔名
filename: "index.html",
}),
],
}
webpack.production.js
執行生產環境下的,打包後會發現 build 目錄下多了一個 index.html 檔案,右鍵單擊 index.html 選擇 open with live server 在瀏覽器檢視一下。如果此時更改 xwh.js 裡 msg 的值,要重新執行命令 npx webpack 之後頁面內容才會更新。
命令: npx webpack
執行開發環境下的。如果此時更改 xwh.js 裡 msg 的值,頁面內容也會隨之改變。
命令: yarn dev
目前實現了生產模式跟開發模式的判斷,也把 html 打包了。
目前存在一個問題,我們平時在做 vue 開發的時候用的是元件,元件的的擴充套件一般是 .vue,xwh.js 是 .js 顯然不是 vue 開發環境,之前在 xwh.js 裡的寫法是 vue1.0 的寫法,所以需要對 vue 的開發環境進行升級。
在 webpack 中,如果要識別除了 js 和 json 以外的檔案,需要安裝 loader 去識別。plugin 的主要作用是擴充套件功能。要識別什麼檔案就使用什麼 loader,比如說,如果要識別 vue 檔案,就用 vue-loader,如果要識別 css 檔案,就用 css-loader。
取得 vue-html-loader。vue-html-loader 用於解析 vue2.0 元件裡的是 template。
命令: yarn add -D vue-html-loader
取得 vue-loader。vue-loader 用於解析 vue 檔案。
命令: yarn add -D vue-loader
取得 vue-template-comiler。vue-template-compiler 是個編譯器,專門用來把 vue 裡的東西分別編譯出來,比如說分別編譯出 html、css、js。
命令: yarn add -D vue-template-compiler
在 src/components 目錄下新建檔案 Xwh.vue,在 src 目錄下新建 App.vue、main.js。
(這些檔案的作用可以參考網路資料:https://blog.csdn.net/qq_34182808/article/details/86690193)
編寫 main.js。引進 vue.esm、App.vue,掛載 App.vue
import Vue from 'vue/dist/vue.esm';
import App from './App.vue';
new Vue({
el:"#app",
components:{
App
},
template:`
<div>
<app></app>
</div>
`
})
main.js
編寫 App.vue。
<template>
<div>
<xwh></xwh>
</div>
</template>
<script>
import Xwh from './components/Xwh.vue';
export default {
name: 'App',
components:{
Xwh
}
}
</script>
App.vue
編寫 Xwh.vue。
<template>
<div>
<h1>
{{ msg }}
</h1>
</div>
</template>
<script>
export default {
name: 'Xwh',
data(){
return{
msg:'許許許'
}
}
}
</script>
Xwh.vue
將 webpack.config.js 的入口路徑由 xwh.js 改為 main.js,寫 loader 的規則,如果有 .vue 結尾的檔案則用 vue-loader 處理。
rules 配置模組的讀取和解析規則,通常用來配置 Loader,配置一項 rules 時大致可通過條件匹配、應用規則、重置順序這幾種方式完成,其中條件匹配是通過 test、include、exclude 三個配置項來選中 Loader 要應用的規則,應用規則是對選中的檔案通過 use 配置項來應用 Loader,可以只應用一個 Loader 或者按照從右往左的順序應用一組 Loader。
const path = require('path');
module.exports = (env) => {
env = env || {};
return {
// entry: "./src/components/xwh.js",
entry: "./src/main.js",
module:{
rules:[
{test:/\.vue$/, use:"vue-loader"}
],
},
...env.development ? require('./config/webpack.development') : require('./config/webpack.production')
};
}
webpack.config.js
因為需要識別 loader,寫好元件之後,在 webpack.development.js 跟 webpack.production.js 引入 vue-loader。
開發環境執行一下,命令: yarn dev
至此,通過各種配置檔案與 loader ,已經基本實現了開發環境。
但是,存在一個問題,在實際的開發中可能會寫一些樣式,還可能需要處理路徑問題。
下面使用 resolve 處理路徑問題,在匯入語句沒帶檔案字尾時,Webpack 會自動帶上字尾去嘗試訪問檔案是否存在。resolve.extensions 用於配置在嘗試過程中用到的字尾列表。設定 extension:['.js', '.json', '.vue'] 的話,當遇到 importAppfrom'./App'; 語句時,webpack 首先會尋找 ./App.js ,如果找不到的話,找 ./App.json,如果找不到的話,找 ./App.vue,如果找不到的話,報錯。嘗試把 App.vue 裡匯入的 vue 檔案的字尾去掉,在命令列輸入 yarn dev 沒有報錯,頁面正常顯示, 說明 resolve.extensions 設定成功。
const path = require('path');
module.exports = (env) => {
env = env || {};
return {
entry: "./src/main",
module:{
rules:[
{test:/\.vue$/, use:"vue-loader"}
],
},
resolve:{
extensions:['.js', '.json', '.vue']
},
...env.development ? require('./config/webpack.development') : require('./config/webpack.production')
};
}
webpack.config.js
可以設定 resolve.alias 來配置項通過別名來將原匯入路徑對映成一個新的匯入路徑。比如說,設定 resolve.alias 後,匯入路徑 importVuefrom'vue/dist/vue.esm'; 可以簡寫為 importVuefrom'vue'; 。在命令列輸入 yarn dev 沒有報錯,頁面正常顯示, 說明 resolve.alias 設定成功。
如果想要設定樣式,需要設定 css-loader 或 style-loader。css-loader 作用是解析 css,style-loader 作用是生成一個內容最終解析為 css 程式碼。
命令: yarn add -D css-loader
命令: yarn add -D style-loader
在 webpack.config.js 寫 loader 的規則,如果有 .css 結尾的檔案則用 css-loader、style-loader 處理。
rules 配置模組的讀取和解析規則,通常用來配置 Loader,配置一項 rules 時大致可通過條件匹配、應用規則、重置順序這幾種方式完成,其中條件匹配是通過 test、include、exclude 三個配置項來選中 Loader 要應用的規則,應用規則是對選中的檔案通過 use 配置項來應用 Loader,可以只應用一個 Loader 或者按照從右往左的順序應用一組 Loader。
const path = require('path');
module.exports = (env) => {
env = env || {};
return {
entry: "./src/main",
module:{
rules:[
{test:/\.vue$/, use:"vue-loader"},
//從右往左,先用 css-loader 讀取 css,再用 style-loader 解析成css規則
{test:/\.css/, use:["style-loader", "css-loader"]}
],
},
resolve:{
extensions:['.js', '.json', '.vue'],
alias:{
vue: 'vue/dist/vue.esm'
}
},
...env.development ? require('./config/webpack.development') : require('./config/webpack.production')
};
}
webpack.config.js
現在可以寫個樣式看看能不能實現了。在 Xwh.vue 裡寫個 row 樣式
<template>
<div class="row">
<h1>
{{ msg }}
</h1>
</div>
</template>
<script>
export default {
name: 'Xwh',
data(){
return{
msg:'許許許'
}
}
}
</script>
<style scoped>
.row{
width: 200px;
height: 120px;
line-height: 120px;
margin: 0 auto;
background-color: #f50;
color: #ffffff;
text-align: center;
}
</style>
Xwh.vue
執行命令 yarn dev ,沒有報錯,網頁有樣式正常顯示。
試試打包會不會有問題,先將之前生成的 build 目錄刪除,然後執行命令 yarn build。執行命令後發現沒有問題,生成了 build 目錄,開啟 index.html 頁面正常顯示。
目前的檔案目錄結構如下:
至此,簡單實現了使用 webpack 搭建 vue 開發環境,基本沒有使用 vue-cli。