1. 程式人生 > 實用技巧 >使用 webpack 搭建 vue 開發環境

使用 webpack 搭建 vue 開發環境

本篇筆記為學習網易公開課後做的筆記,課程是網易譚金龍老師講的, 地址:https://study.163.com/sl/VsaN

請勿直接爬走,本文地址:https://www.cnblogs.com/xiaoxuStudy/p/13492608.html

本篇筆記的內容不一定完全正確,因為我有的地方不懂,先把筆記做下來, 如果有錯誤的地方麻煩指出,謝謝。

目錄:

1. vue-cli 的工作原理

2. 用 webpack 搭建 vue 專案

一. vue-cli 的工作原理

  如果為了“開箱即用”,可以使用命令 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

,因為如果不同的專案是基於不同的 webpack 但是又全域性安裝了 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 專案

下面利用 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。