手把手教你使用webpack實現vue-cli

2022-10-07 10:00:44

前端(vue)入門到精通課程:進入學習
API 檔案、設計、偵錯、自動化測試一體化共同作業工具:

當我們剛開始學習vue的時候我們都是使用vue-cli來搭建一個基礎的vue專案的基礎目錄結構,並且實現使用npm run serve,啟動我們的vue專案並在本地跑一個8080埠的服務,並且當我們修改並儲存時,原生的埠頁面也會隨之重新整理,類似於live-server的功能。相關推薦:】

前言

要想實現一個vue-cli的腳手架,我們先要了解什麼是webpack?如何使用webpack?

1.png

本質上,webpack 是一個現代 JavaScript 應用程式的靜態模組打包器(module bundler) 。當 webpack 處理應用程式時,它會遞迴地構建一個依賴關係圖(dependency graph) ,其中包含應用程式需要的每個模組,然後將所有這些模組打包成一個或多個 bundle。其中包括四個核心概念:

  • 入口(entry)
  • 輸出(output)
  • loader
  • 外掛(plugins)

接下來,我們一邊來實現vue-cli給我們搭建的基礎結構,一邊來簡單說一說webpack的核心概念。

vue-cli實現過程

首先我們開啟一個資料夾,在當前資料夾下開啟終端,首先在終端執行npm init -y,使得當前檔案下具備package.json的檔案,這樣我們的這個專案就可以從(node庫 (npmjs.com))裡去安裝我們所需要的依賴,首先我們去使用終端安裝 webpack 和 webpack-cli ,在終端中執行npm install webpack webpack-cli(或者npm i webpack webpack-cli)

首先我們在專案的根目錄下,建立一個index.html,只在其中放一個id為app的容器




  
  
  


  
登入後複製

在根目錄下建立一個src資料夾,裡面建立一個main.js,通常情況下我們在vue專案裡都是用.vue字尾的檔案來寫元件或者是頁面(通常我們所謂的頁面,實際只是藉助路由跳轉,不算真正意義的頁面,通常我們會稱之為頁面),因為我們沒有使用vue-cli搭建專案,所以並沒有把vue的原始碼和webpack相結合,所以我們要手動引入vue的原始碼,使得我們可以使用vue的語法,那麼我們應該先使用node安裝一個vue的原始碼在終端中執行npm i vue,因為最新的我們是引入了vue3的原始碼,所以不再是將整個vue範例物件引入到專案中,因為在vue3中為了提高效能,所有的程式碼都是按需引入的,而不是像vue2一樣將整個vue的範例物件引入到專案中,直接去使用範例物件上的方法。

如果我們不在專案裡引入vue的原始碼,那我們在main.js中只能寫原生js的語法,如下:

未引入vue原始碼的main.js:

function comp() {
  const el = document.createElement("div");

  el.innerHTML = '你好,vue-cli'

  return el
}

document.body.appendChild(comp())
登入後複製

2.png

那如果我們再給他加點樣式,應該怎麼辦呢?理論上而言webpack只能打包js檔案,那css、less、以及vue字尾的檔案它是怎麼處理的呢?我們一步一步來看,既然是vue專案,我們通常都是寫vue字尾的檔案,有時候寫專案為了方便同樣也會在src檔案下建一個style的資料夾,裡面處理一些專案裡的公共樣式,但在此處,我們就不再巢狀資料夾,其實原理都是一樣的,如果巢狀資料夾,只需要將檔案的路徑更改一下就能實現。

main.js

import { createApp } from 'vue';
import './style.css'
import App from './App.vue'

const app = createApp(App)
app.mount('#app')
登入後複製

在src目錄下,我們新建一個style.css檔案和一個App.vue,其程式碼如下:

style.css:

div{
  color: red;
}
登入後複製

App.vue:





登入後複製

專案其中基本的檔案型別就是這些,如果你需要使用到.less的檔案或者.stylus檔案等,那麼我們在webpack的四大核心之一的loader中去設定一些規則,使得將.less的檔案或者.stylus檔案先轉化為.css檔案,再告訴webpack去載入CSS檔案

既然要使用webpack的核心功能那麼首先我們應該在根目錄下建立一個webpack的組態檔webpack.config.js接下來我帶著大家一起來一個一個核心部分來了解。

入口(entry)

入口起點(entry point) 指示 webpack 應該使用哪個模組,來作為構建其內部依賴圖的開始。進入入口起點後,webpack 會找出有哪些模組和庫是入口起點(直接和間接)依賴的。 可以通過在 webpack 設定中設定 entry 屬性,來指定一個入口起點(或多個入口起點)。預設值為 ./src

module.exports = {
  entry: './src/main.js', // 專案入口檔案(打包這個檔案)
};
登入後複製

根據應用程式的特定需求,可以以多種方式設定 entry 屬性。從入口起點章節可以瞭解更多資訊。

出口(output)

output 屬性告訴 webpack 在哪裡輸出它所建立的 bundles,以及如何命名這些檔案,預設值為 ./dist。基本上,整個應用程式結構,都會被編譯到你指定的輸出路徑的資料夾中。你可以通過在設定中指定一個 output 欄位,來設定這些處理過程:

const path = require('path'); // node 提供的方法獲取絕對路徑

module.exports = {
  entry: './src/main.js', // 專案入口檔案(打包這個檔案) 
  output: { 
      path: path.resolve(__dirname,'dist'), // webpack要求必須要絕對路徑,__dirname專案檔案的絕對路徑 
      filename: 'js/[name].[contenthash].js' // 生成打包程式碼重新命名 js[name].js 預設main.js 
     },
};
登入後複製

可能你想要了解在程式碼最上面匯入的 path 模組是什麼,它是一個 Node.js 核心模組,用於操作檔案路徑。

Babel用法

在實際開發中我們很少直接去接觸babel,但是babel對於前端開發來說又是必不可少的。Babel到底是什麼呢,它其實是一個工具鏈,跟postcss一樣,它能夠將ECMAScript後版本語法程式碼轉為ES5程式碼,包括:語法轉換、原始碼轉換、Polyfill實現功能。

babel核心安裝

我們來安裝babel核心庫@babel/core,如果我們想要在命令列使用需要安裝@babel/cli,安裝npm install @babel/core @babel/cli。我們如果想使用babel的功能,就需要安裝bable的外掛,我們可以使用babel的預設外掛@babel/preset-env,安裝npm install @babel/preset-env -D

babel.config.js:

module.exports = {
  presets: [
    ["@babel/preset-env", {
      "targets": {
        "browsers": ["last 2 versions"]
      }
    }]
  ]
}
登入後複製

儘管現在市面上主流的瀏覽器已經適配了es6的語法,但是我覺得js語法降級也是我們需要掌握的;

loader

loader 讓 webpack 能夠去處理那些非 JavaScript 檔案(webpack 自身只理解 JavaScript)。loader 可以將所有型別的檔案轉換為 webpack 能夠處理的有效模組,然後你就可以利用 webpack 的打包能力,對它們進行處理。

本質上,webpack loader 將所有型別的檔案,轉換為應用程式的依賴圖(和最終的 bundle)可以直接參照的模組。

注意,loader 能夠 import 匯入任何型別的模組(例如 .css 檔案),這是 webpack 特有的功能,其他打包程式或任務執行器的可能並不支援。我們認為這種語言擴充套件是有很必要的,因為這可以使開發人員建立出更準確的依賴關係圖。

在更高層面,在 webpack 的設定中 loader 有兩個目標:

  • test 屬性,用於標識出應該被對應的 loader 進行轉換的某個或某些檔案。

  • use 屬性,表示進行轉換時,應該使用哪個 loader。

const path = require('path');  // node 提供的方法獲取絕對路徑
module.exports = {
  mode: 'development', // 開發模式(打包出來的程式碼不會被壓縮)轉化為html、css、js,圖片壓縮等
  entry: './src/main.js', // 專案入口檔案(打包這個檔案)
  output: {
    path: path.resolve(__dirname,'dist'),  // webpack要求必須要絕對路徑,__dirname專案檔案的絕對路徑
    filename: 'js/[name].[contenthash].js' // 生成打包程式碼重新命名 js[name].js  預設main.js
  },
  module: {
    rules: [
      {
        test: /\.css$/i,  //正規表示式
        use: ['style-loader', 'css-loader']  // 從右向左執行,有先後順序 
      },
      {
        test: /\.vue$/i,  //正規表示式
        use: ['vue-loader']  // 從右向左執行,有先後順序 
      },
      {
        test: /\.js$/i,  //正規表示式
        exclude: '/node_modules',
        use: ['babel-loader']
      }
    ]
  }
}
登入後複製

在一般的vue專案中我們需要使用node安裝三個loader npm i style-loadernpm i css-loadernpm i vue-loader,同時還需要一個vue的編譯外掛npm i @vue/compiler-sfc,其作用是將vue的語法編譯成抽象語法樹(虛擬dom結構),

3.png

換句話說就是將.vue檔案的三個部分取出來,分別放到`script` 、 `template` 、 `style` 三個部分中去。

外掛(plugins)

loader 被用於轉換某些型別的模組,而外掛則可以用於執行範圍更廣的任務。外掛的範圍包括,從打包優化和壓縮,一直到重新定義環境中的變數。外掛介面功能極其強大,可以用來處理各種各樣的任務。

想要使用一個外掛,你只需要 require() 它,然後把它新增到 plugins 陣列中。多數外掛可以通過選項(option)自定義。你也可以在一個組態檔中因為不同目的而多次使用同一個外掛,這時需要通過使用 new 操作符來建立它的一個範例。

首先為了打包之後生成一個新的html的檔案,我們需要安裝一個外掛npm i html-webpack-plugin -D該外掛將為你生成一個 HTML5 檔案,組態檔如下:

const HtmlWebpackPlugin = require('html-webpack-plugin'); // 通過 npm 安裝
const path = require('path');  // node 提供的方法獲取絕對路徑
const { VueLoaderPlugin } = require('vue-loader/dist/index')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')  
module.exports = {
  mode: 'development', // 開發模式(打包出來的程式碼不會被壓縮)轉化為html、css、js,圖片壓縮等
  entry: './src/main.js', // 專案入口檔案(打包這個檔案)
  output: {
    path: path.resolve(__dirname,'dist'),  // webpack要求必須要絕對路徑,__dirname專案檔案的絕對路徑
    filename: 'js/[name].[contenthash].js' // 生成打包程式碼重新命名 js[name].js  預設main.js
  },
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: ['style-loader', 'css-loader']  // 從右向左執行,有先後順序 
      },
      {
        test: /\.vue$/i,
        use: ['vue-loader']  // 從右向左執行,有先後順序 
      },
      {
        test: /\.js$/i,
        exclude: '/node_modules',
        use: ['babel-loader']  // 我們安裝的一個外掛,使得es6之後的語法轉化為es5
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: path.resolve(__dirname,'./index.html'),  // 需要打包的html檔案的絕對路徑
      filename: 'index.html',   // 打包之後的檔案可以重新命名
      title: '手動搭建vue-cli'   //還可以修改打包後的HTML中的title
    }),
    new VueLoaderPlugin(),
    new CleanWebpackPlugin() // 清除上一次打包的內容刪除,使得下一次的打包順利進行
  ]
}
登入後複製

在外掛中修改HTML的title,需要在HTML中寫一行程式碼<title><%= htmlWebPlugin.options.title%></title>, htmlWebPlugin就是我們在plugin裡new出來的範例物件,同時我們之前安裝的vue-loader的功能不僅僅是幫我們去讀懂.vue字尾的檔案,我們也可以當一個外掛來使用;首先引入const { VueLoaderPlugin } = require('vue-loader/dist/index'),在plugin裡面new一下我們參照的這個建構函式,它的作用是將我們定義過的規則複製並應用到.vue檔案相應的語法塊中。

模式

通過選擇 development開發模式 或 production 生產模式之中的一個,來設定 mode 引數,你可以啟用相應模式下的 webpack 內建的優化

module.exports = {
  mode: 'production'
};
登入後複製

到現在我們基本的vue-cli的功能已經實現了,但是我們會發現,我們使用vue-cli執行專案的時候我們是直接跑了一個本地埠的服務,所以我們只需要在最後設定一下DevServer

devServer: {
    static: {
      directory: path.join(__dirname, 'dist'),  // 跑起來的服務的檔案
    },
    compress: true,  // 是否壓縮
    port: 8080,   // 本地開啟服務的埠號
    open: true  // 執行服務之後是否自動開啟
  }
登入後複製

package.json

{
  "name": "vue-cli",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack",    //我們使用 npm run build 將專案打包至dist資料夾
    "dev": "webpack serve" // 我們使用 npm run dev 將專案執行起來
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.19.1",
    "@babel/preset-env": "^7.19.1",
    "babel-loader": "^8.2.5",
    "clean-webpack-plugin": "^4.0.0",
    "css-loader": "^6.7.1",
    "html-webpack-plugin": "^5.5.0",
    "style-loader": "^3.3.1",
    "vue": "^3.2.39",
    "webpack": "^5.74.0",
    "webpack-cli": "^4.10.0",
    "webpack-dev-server": "^4.11.1"
  },
  "dependencies": {
    "@vue/compiler-sfc": "^3.2.39",
    "vue-loader": "^17.0.0"
  }
}
登入後複製

完整的webpack.config.js組態檔:

const HtmlWebpackPlugin = require('html-webpack-plugin'); // 通過 npm 安裝
const path = require('path');  // node 提供的方法獲取絕對路徑
const { VueLoaderPlugin } = require('vue-loader/dist/index')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
module.exports = {
  mode: 'development', // 開發模式(打包出來的程式碼不會被壓縮)轉化為html、css、js,圖片壓縮等
  entry: './src/main.js', // 專案入口檔案(打包這個檔案)
  output: {
    path: path.resolve(__dirname,'dist'),  // webpack要求必須要絕對路徑,__dirname專案檔案的絕對路徑
    filename: 'js/[name].[contenthash].js' // 生成打包程式碼重新命名 js[name].js  預設main.js
  },
  module: {
    rules: [
      {
        test: /\.css$/i,
        use: ['style-loader', 'css-loader']  // 從右向左執行,有先後順序 
      },
      {
        test: /\.vue$/i,
        use: ['vue-loader']  // 從右向左執行,有先後順序 
      },
      {
        test: /\.js$/i,
        exclude: '/node_modules',
        use: ['babel-loader']
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: path.resolve(__dirname,'./index.html'),
      filename: 'index.html',
      title: '手動搭建vue-cli'
    }),
    new VueLoaderPlugin(),
    new CleanWebpackPlugin()
  ],
  devServer: {
    static: {
      directory: path.join(__dirname, 'dist'),
    },
    compress: true,
    port: 8080,
    open: true
  }
}
登入後複製

實際效果展示:

4.gif

(學習視訊分享:、)

以上就是手把手教你使用webpack實現vue-cli的詳細內容,更多請關注TW511.COM其它相關文章!