Vue2 從 Webpack4 遷移到 Vite
前陣子幫公司完成了 Vue2 老專案升級。從 node10 升到 node16,並從 @rails/webpacker
(webpack4) 成功遷移到了 vite。
這篇來給自己紀錄一下。
## 目錄
- 情境介紹
- 關於 Rails Webpacker
- 重建 Node.js Webpack Config
- @rails/webpacker 依賴 node-sass
- 棄用 @babel/polyfill
- postcss-loader 的順序
- postcss 插件 autoprefixer 與 browserslist
- 處理 css 要區分 dev 與 build
- 遷移到 Vite
- import 需加上 .vue 副檔名
- sass 的 /deep/ 寫法變更
- sass v2 棄用顯示數學計算
- 在 css import node_modules
- jsx 用法變更
- process.env 不可用
- vite 不支援 CommonJS 需改為 ESM
- vite build 需另外設定處理 CommonJS
- webpack require.context() 不可用
- vite 與 webpack5 不再提供 path 等 polyfill
- 處理 css :export
- 替代 webpack svg-sprite-loader
- pnpm ignore missing peer 警告
- build 後 el-table 呈現空白
- element-ui 自訂 theme 被 umy-ui 搶 css 權重
- vite 中 template whitespace 間隔消失
- ES6+ 語法出現 VScode ts 報錯
情境介紹
# 專案環境
- Ruby on Rails 前後端共構專案 (使用 Webpacker)
- 前端透過 @rails/webpacker 構建 Vue2
- node10,有 node-sass
- 當前是 Server build,Node.js 版本被 Server 限制
一直以來這個前端專案就很想脫離 Rails 的掌控,分離出來獨立維護。前端環境從 node14 開始有了許多的變化,Node.js 不再能無腦向下兼容。
最近紛紛出現使用 Mac M1 的同事,遇上了 node10 無法安裝的問題,再加上 node-sass 等舊套件已被棄用,無法運作於 node12 以上環境等因素,早晚都得面對專案升級的問題。
於是,趁著工作的空閒期,嘗試將專案升級。目標大致如下:
- 升級 Node.js 版本,至少到 14 or 16
- 脫離 @rails/webpacker 依賴
- 前後端 git repo 分離
- 遷移至 Vite
關於 Rails Webpacker
先說明一下 Rails Webpacker 這玩意是啥,它是類似 vue-cli、create-react-app 那種 webpack 腳手架,不過是 Ruby on Rails 的版本,但它已不再維護。
當前版本內部使用 webpack4,並內置 node-sass 等等,當時主流的前端工具。由於它是針對 Rails 來建構的,所以會出現一些前端不熟悉的配置。
不過 webpack 配置本質上都是差不多的,只要搞清楚 config 在哪、html 進入點、js 進入點這些東西,就能夠重架一個 Node.js 主導的 webpack 配置。
先網上查詢關於 Rails Webpacker 的文章,然後找出核心配置有哪些,其他的可以不用太深入。
對照此專案的情況,可以整理出這些檔案。
# rails webpacker 設定檔
config/webpacker.yml
# 終端機 cli 的執行檔
bin/webpack
bin/webpack-dev-server
# webpack 設定檔
config/webpack/custom.js (非預設)
config/webpack/environment.js
config/webpack/development.js
config/webpack/production.js
// ...
# js 進入點
app/javascript/pack/application.js
app/javascript/pack/main.js (非預設)
# vue 的 source files
app/javascript/src/**/*
# html 進入點
app/views/layouts/application.html.erb
app/views/layouts/vue.html.erb (非預設)
app/views/vue/index.html.erb
在 webpacker 的設定檔 config/webpacker.yml
可以找到 inpurt 與 output 設定。
# config/webpacker.yml
source_path: app/javascript
source_entry_path: packs
public_root_path: public
public_output_path: packs
從 source_xxx
得知 input 在 app/javascript/packs/*
底下,似乎預設會是 application.js
,但我這專案改成了 main.js
。而 output 則會根據 public_xxx
的設定 build 到 public/packs/*
。
執行檔是用 rails cli 指令,進行 dev 啟動或 build 時,會根據那兩個檔案的內容去調用 webpack。
# 縮寫 rails s, 後端 dev 啟動
# 進到 vue 頁面會執行 bin/webpack
$ rails server
# 依據 Procfile 的設定同時啟動前後端 dev server
# 這邊會調用 bin/webpack-dev-server
$ foreman start
# 前端 build
rake assets:precompile
再來是 webpack 的設定檔,裡面有很多個,但從命名可以看出那只是區分成 development、production、test 不同模式而已。
從內容可以推斷出核心檔案是 environment.js
,不同模式的檔案都會引入它。我這專案有另外寫一個 custom.js
,這支會在 environment.js
被引入,用來覆蓋預設設定。
而 custom.js
這支檔案的寫法與 webpack config 是一樣的,所以就可以從這支檔案得知具體設定。
js 進入點沒甚麼特別的機制,但 html 進入點就比較麻煩,因為他是 .erb 檔,可以視作 Rails 的模板文件,它會接收一些從 Rails render 出來的內容。
大概是長這樣。
<!-- app/views/layouts/vue.html.erb -->
<head>
<%= javascript_pack_tag 'main' %>
<%= stylesheet_pack_tag 'main' %>
<%= csrf_meta_tags %>
<!-- ... -->
</head>
<body>
<div class="container" data-behavior="app">
<%= render 'path/to/file' %>
<%= yield %>
</div>
</body>
那些看起來奇怪的 html <%= … %>
是 erb 的模板語法。head 裡面的 javascript_pack_tag
是指定在這邊塞 webpack 編譯後的 js 檔,顧名思義,這段會去 app/javascript/pack/*
底下尋找 main.js
。而後面兩個我這專案實際運行確認是空的,所以不理它。
body 底下的 render
從命名可以看出,這邊是插入指定的模板組件進來。我這專案引入的只是一塊版本資訊的 banner,先不理它,之後可以在 Vue 裡面重做。
另一個 yield
,則會導入 rails contoller 定義的模板。
# app/controllers/vue_controller.rb
class VueController < ApplicationController
layout 'vue'
def index
end
end
# app/views/vue/index.html.erb
<div id="app"></div>
layout 'vue'
指的是 app/views/*
底下的 vue
資料夾,然後再指向裡面的 index.html.erb
。
確認 Rails 注入的東西有哪些之後,就可以改寫回單純的 index.html 了。
如此,進入點都找到了,也有 config 了,那就可以進入下一步。
重建 Node.js Webpack Config
先嘗試重建 webpack config,讓 Node.js 可以執行 dev 啟動以及 build,脫離 Rails 控制。
除了上述的核心檔案之外,也別忘了根目錄底下各式 js 相關的 config:
# npm & js 設定
package.json
yarn-lock (or package-lock.json or pnpm-lock.yaml)
jsconfig.json (or tsconfig.json)
.nvmrc
# babel (JS 編譯器)
.babelrc
# postcss (css 後處理器)
postcss.config.js
.browserslistrc
# eslint (風格規範)
.eslintignore
.eslintrc.js
# prettier (auto formatter)
.prettierrc.js
原本 webpack 是 @rails/webacker
底下的子依賴,實際並沒有安裝。
需先補安裝。可以在 lock 檔確認 @rails/webpacker
使用的 webpack 版本。
$ yarn add webpack@"^4.41.2"
$ yarn add webpack-cli@"^3.3.10"
$ yarn add webpack-dev-server@"3.10.1"
補上 npm scripts。
// package.json
"scripts": {
"dev": "webpack-dev-server",
"build": "webpack --mode production"
// ...
}
接著新增 webpack.config.js
,把 config/webpack/custom.js
搬過來,就可以嘗試啟動,進入除錯之旅。
但我因為想順便複習一下 webpack,所以找了一篇教學從零一個一個去設定。
我這專案的情況,照這教學做完,再跟原本 custom.js
的設定核對之後,就能順利啟動了。
webpack 這玩意麻煩在它不是開箱即用的,幾乎所有設定都要自己去弄。不過概念上也不複雜,就是每一個 assets 都要告訴 webpack 要如何解析。無非就是指定 css 使用這個 loader,img 使用那個 loader,然後設定細節。
確認 Node.js 端啟動沒問題之後,可以新建 repo 搬過去了,不確定的話就直接抄 vite 或 vue-cli 的目錄結構。
# 新建專案
public
favicon.ico
logo.svg
src
...
App.vue
main.js # 原本在 rails 是單獨放置, 現在將它放到 src 裡面
index.html
...configs
搬移之後,修改 webpack config 的 entry、output、alias 那些路徑。
接著移除 @rails/webpacker
。
$ yarn remove @rails/webpacker
再嘗試啟動,由於 webpacker 內包的子依賴已移除,會發現需要補裝一些套件,我的情況是這些:
{
"node-sass": "^4.14.1",
"postcss": "^7.0.39",
"postcss-flexbugs-fixes": "^4.2.1",
"postcss-import": "^12.0.1",
"postcss-preset-env": "^6.7.0",
"sass-loader": "^7.3.1",
}
現在,已經成功將前端獨立拆了出來,脫離了 Rails Webpacker 依賴。再來就是系統升級了。
移除 node-sass,更換為 sass。它的兼容性很強,可以無腦安裝最新版,當前是 v1.66.1。
$ yarn remove node-sass
$ yarn add sass
這邊要注意一下,換成 sass 之後原本 /deep/
的寫法被棄用,需要改成 :deep
,直接 VSCode 搜尋替換就好。
/* node-sass */
/deep/.my-style {}
/* sass */
:deep .my-style {}
接著升級 Node.js。用 nvm 之類的版本管理器切換到 node16,然後移除 node_modules
與 yarn-lock
重裝套件。並依喜好,順道將 yarn 更換成 pnpm。
# 切換 node16
$ nvm install 16
$ nvm use 16
# 啟用 pnpm 並更新到最新
$ corepack enable
$ corepack prepare pnpm@latest --activate
# 以 node16 與 pnpm 重裝套件
$ pnpm install
然後測試 dev 啟動以及 build,確認沒問題之後就告個段落。
成功完成了:
- Node.js 升級至 v16
- 脫離 @rails/webpacker 與 node-sass 依賴
- 前後端分離
流水帳記錄一下 webpack config 重建遇上的坑。
@rails/webpacker 依賴 node-sass
node-sass,只能運行在 node12 以下版本。這是因為它使用了 node-gyp
牽扯到 python 一些雜七雜八的。Mac M1 由於架構不同會裝不上去。
升級到 node14+ 之後,只要將套件換成 sass
就行了,webpack 的話要記得 sass-loader
也要升。
棄用 @babel/polyfill
babel 7.4.0 開始棄用 @babel/polyfill
,改用 @babel/preset-env
,設定方式不一樣。前者會寫在 webpack config 上,後者會寫在 babel config 上。
postcss-loader 的順序
webpack 的 loader 設定採用 Array,但執行順序是「反著來的」,它會從後面的 loader 先開始解析。
所以使用 Sass + postcss 時,postcss-loader 要放在 sass-loader 的前面,先解析 Sass 完成之後,postcss 才能接手。
module: {
rules: {
{
test: /\.(sass|scss)$/,
use: ['vue-style-loader', 'css-loader', 'postcss-loader', 'sass-loader'],
},
}
}
postcss 插件 autoprefixer 與 browserslist
autoprefixer 透過 postcss 驅動,幫 css 添加 -webkit-
這些兼容性前綴。同時它會根據 .browserslistrc
的設定編譯成不同內容。
browserslist 這玩意也會影響到 babel,如果指定兼容比較舊的瀏覽器,會造成 ?.
以及 ??
這些 js 新語法在編譯時報錯,需要補裝相關 plugin。
# 處理 ?.
@babel/plugin-transform-optional-chaining
# 處理 ??
@babel/plugin-transform-nullish-coalescing-operator
然後這個 autoprefixer
在 postcss 新版本已可用 postcss-preset-env
取代。
處理 css 要區分 dev 與 build
啥都不設定的話,webpack 預設會將 css 打包到 js 裡面,造成 js 過度肥大。
dev 啟動一般會用 style-loader
(vue 使用 vue-style-loader
) 將 css 編譯到 <style> 裡面往 html 塞。
build 則會希望打包成獨立的 .css file,這就必須將 style-loader
替換為 mini-css-extract-plugin
。
可以使用 webpack-merge
來分割 dev 與 prod build 的 webpack config。
遷移到 Vite
成功將前端分離出來之後,接著嘗試從 webpack4 遷移到 vite。在 config 與插件部分,因為 Vite 開箱即用,比 webpack 要簡單許多。
先把 vite 與 Vue2 相關插件裝上,jsx 插件則看專案有沒有用到。
$ pnpm i -D vite @vitejs/plugin-vue2 @vitejs/plugin-vue2-jsx
加入 npm scripts,webpack 的內容可以先保留,遷移完成再移除。
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview",
"dev:w": "webpack-dev-server",
"build:w": "webpack --mode production",
},
建立 vite config 配置,比起 webpack 相當的精簡。
// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue2'
import vueJsx from '@vitejs/plugin-vue2-jsx'
import path from 'node:path'
export default defineConfig({
plugins: [vue(), vueJsx()],
resolve: {
alias: {
'@': path.join(__dirname, 'src'),
// ...
},
},
})
然後這些東西可以全砍了。
# webpack
webpack
webpack-dev-server
webpack-cli
webpack.config.js
# webpack loaders
vue-loader
css-loader
// ...
# webpack plugins
mini-css-extract-plugin
html-webpack-plugin
// ...
# babel
@babel/core
@babel/preset-env
// ...
# postcss
postcss
postcss-import
cssnano
// ...
webpack 相關的東西,特別是那一大堆的 loader 與 plugins 都不再需要了。
postcss 在 vite 雖有內建,但
postcss-preset-env
沒內建,要另外裝。
babel 除非有特殊需求,不然在 IE 已經正式走入歷史的現在,for 現代瀏覽器的 vite,babel 已不再是標配。需要編譯 jsx 的話,vite 有專門的 plugin。
如果真有兼容老瀏覽器的需求,可以裝 @vitejs/plugin-legacy
,裡面已包好 babel 配置。
再來就是嘗試啟動的除錯之旅。
vite 雖然在 config 沒有一堆煩人的 loader 與 plugins,但這只是在設定上比較精簡,實際跟 webpack 環境還是有很多需要磨平的地方。
import 需加上 .vue 副檔名
webpack4 環境多數會設定省略 .vue 副檔名。 vite + Vue3 環境則是強烈建議加上副檔名,以便 VScode + Volar 獲取 type 定義。
// 加上 .vue
import App from './App.vue'
可是一個一個去加 .vue 太吐血了,vite 現在也支援 webpack 同款設定,去省略副檔名。
// vite.config.js
resolve: {
extensions: ['.mjs', '.js', '.mts', '.ts', '.vue'], // 省略副檔名
},
sass 的 /deep/ 寫法變更
前面有提過,雖然不是 vite vs webpack 的問題,但還是要注意一下。原本舊的 /deep/
寫法要改成 :deep
。
這種寫法 /deep/.my-class
替換時要注意加空格 :deep .my-class
。而更新的版本會要求使用 :deep()
。
雖然這嚴格來說不是 sass 的語法,但它會被 sass 或其他預處理器的版本所影響。
sass v2 棄用顯示數學計算
sass v1.32 以上版本,會出現棄用提示,不再支持直接的數學計算寫法。
// NG
1 / 5
要改成這種 function 調用的寫法。
// OK
calc(1 / 5)
math.div(1, 5)
如果有用 element-ui,它內部 Sass 有用舊的數學寫法,會一直噴警告,只能將 sass 退版到 ~1.32
,忽略警告。
在 css import node_modules
webpack 支持使用波浪號 ~
在 css 導入 node_modeuls。但這個 vite 看不懂,vite 是採用跟 js 同款寫法來處理。
// webpack
@import "~element-ui/packages/theme-chalk/src/index";
// vite
@import "element-ui/packages/theme-chalk/src/index";
懶得手動修改的話,可以透過 alias 設定,讓 vite 辨識波浪號。
resolve: {
alias: [
// 正規判斷 ~ 開頭, 指向 node_modules
{
find: /^~(?!\/)/,
replacement: path.join(__dirname, 'node_modules/'),
},
],
}
jsx 用法變更
webpack 環境下,隨著 babel 等相關插件的新舊版本差異,jsx 的用法略有不同。而 vite 這邊畢竟比較新,可直接在 <script setup> 裡面使用 jsx。
但要注意,vite 中使用 jsx 需要打上 lang
標記作為識別符號。
<script lang="jsx">
// ...
</script>
process.env 不可用
process.env
為 Node.js 語法,在 vite 中不可用,需以 import.meta
替代。
// webpack
process.env.NODE_ENV
// vite
import.meta.env.MODE
vite 不支援 CommonJS 需改為 ESM
vite 使用 ESM 而不是 CommonJS,需將 require / module.exports 改為 import / export。
// NG
const axios = require('axios')
module.exports = { foo: 'bar' }
// OK
import axios from 'axios'
export default { foo: 'bar' }
社群也有人製作 vite 的 CommonJS 插件 vite-plugin-commonjs
,懶得手動改的話可以試試。
另外 webpack 還有 script-loader 提供的特殊語法。雖然我這專案有這行 code,但排查後發現沒有被使用到,我就先跳過了。
// webpack + script-loader
require('script-loader!jsonlint')
目前只知道 script-loader 在做的事,是把目標 js 引入後,直接在 global 執行一次。也就是該 js 的內容會註冊到 window 上可供調用。
我查不到 vite 該如何實現等價操作,但這專案的這段 code 研究了一下,主要是用 codemirror + jsonlint 在瀏覽器上弄一個 JSON 編輯器出來。
網上比較新的相關教學,是使用模塊化版本的 jsonlint-mod
來做,這樣就不需要使用到 script-loader 了。
import jsonlint from 'jsonlint-mod'
window.jsonlint = jsonlint
vite build 需另外設定處理 CommonJS
如果選擇使用 vite-plugin-commonjs
,那在 build 時會碰到問題,因為這插件是 for dev mode 的。
另外,也可能會碰到老套件內部使用 CommonJS,我們無法去改它。只能透過 vite-plugin-commonjs
來處理。
這樣在 build 時,要去設定 rollup 轉換 CommonJS。
// vite.config.js
build: {
commonjsOptions: {
transformMixedEsModules: true, // 轉換兼容 commonjs
},
},
webpack require.context() 不可用
require.context()
是 webpack 提供的特殊語法,可用來獲取資料夾目錄,實現自動化導入。這個 vite 自然是看不懂的。
但 vite 有等價語法,可用 import.env.glob 來改寫。例如要匯入 files 資料夾裡的所有 js:
// webpack
const files = require.context('./files', true, /\.js$/)
const fileObj = files.keys().reduce((obj, path) => {
const file = files(path)
obj[path] = file.default
return obj
}, {})
// vite
const files = import.meta.glob('./files/*.js', { eager: true })
const fileObj = Object.keys(files).reduce((obj, path) => {
const file = files[path]
obj[path] = file.default
return obj
}, {})
要注意回傳的東西不太一樣,require.context()
回傳的是 function,並帶有 props。而 import.meta.glob()
則是回傳一個 object。
vite 與 webpack5 不再提供 path
等 polyfill
path
是 Node.js 提供的模塊,並不是瀏覽器有的東西。
如今 vite 與 webpack5 都不再提供 polyfill,在瀏覽器端執行的 code,不能直接引入使用。
vite 環境下,瀏覽器端的 code 原則上都不該使用 path
這些 Node.js 的功能了。但是老 code 已經這樣寫了,怎麼辦?
可以安裝瀏覽器版本 path-browserify 頂一下,但最好找時間把有用到的地方重寫。安裝之後,利用 alias 設定來映射。
// vite.config.js
resolve: {
alias: {
// remapping to path-browserify
path: 'path-browserify',
},
},
如果老 code 有用到 path.resolve()
會很麻煩,它會在內部以 global 的方式調用 process.cwd()
。
這雖然也有瀏覽器版本 process。
但由於它是在 global 被調用的,沒有使用 import 關鍵字,所以無法設定 alias 來處理,得用比較 cheat 的做法,將其在 html 頭部導入後,掛到 window 上面。
<!-- index.html -->
<script type="module">
import process from 'process'
window.process = process
</script>
處理 css :export
webpack 的 css-loader
有提供一種 :export
語法,讓 js 可以 import 在 css 或 sass 中被定義的變數。
而在 vite 則透過 css-modules
支援此語法,但要將有用到 :export
的檔案更名為 css modules 的格式,添加中間名 xxx.module.css
。
另外要注意,如果在有使用 :export
的檔案中 import node_modules 的話,vite 會把套件裡面定義的變數也全都導出,嚴重影響編譯速度。
// somthing.scss
$--color-primary: #1890ff;
/* js import 時,vite 會將 element-ui 內的變數也全數導入 */
@import "element-ui/packages/theme-chalk/src/index.scss";
:export {
theme: $--color-primary;
}
這部分要視專案情況改寫,把 import 跟 :export 分離開來。
替代 webpack svg-sprite-loader
svg-sprite-loader
這玩意顧名思義是用精靈圖的概念去一次性導入 svg 檔案。
如果有用到這個,應該會有一段使用 require.context() 批次導入 svg icon 的 code,並依靠該 loader 在導入時自動註冊 svg。
// 自動導入 ./svg 資料夾下的所有 .svg files
const req = require.context('./svg', false, /\.svg$/)
const requireAll = (requireContext) => {
return requireContext.keys().map(requireContext)
}
requireAll(req)
vite 有個等價的插件 vite-plugin-svg-icons
,並且會把自動導入部分也處理好,所以上面那段 code 可以直接砍掉,改去 config 設定就好。
// vite.config.js
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
export default defineConfig({
plugins: [
// svg 預加載, 替代 webpack svg-sprite-loader
createSvgIconsPlugin({
// 指定 dir 自動導入
iconDirs: [path.join(__dirname, 'src/icons/svg')],
// svg-sprite-loader 會打上一個供調用的 id
// 這邊設成一樣的讓老 code 能呼叫到
symbolId: 'icon-[name]',
}),
],
})
pnpm ignore missing peer 警告
vite 有很多套件的 core 都內建了,只要安裝相關 plugin 就好,例如要使用 postcss-preset-env
時,並不需要安裝 postcss
。
但是 pnpm 會偵測到它依賴 postcss
,可它在 vite 底下,pnpm 不做深度檢查,所以它會誤判沒有安裝 peer 依賴,跳出 missing peer 警告。
另外像是 ant-design-vue
也有設定依賴 vue-template-compiler
,可是 vite 不需要裝這個,pnpm 也會跳出警告。
這問題可以在 package.json 設定 pnpm ignore missing peer 解決。
// package.json
{
"pnpm": {
"peerDependencyRules": {
"ignoreMissing": ["vue-template-compiler", "postcss"]
}
}
}
build 後 el-table 呈現空白
如果使用 element-ui
與 Vue2.7,可能會碰到 dev 啟動一切正常,但 build 後 el-table 卻 render 空白的情況。
這似乎是 vue2.7 採用新版 vue-template-complier
與 element-ui 內部寫法衝突導致的問題。在 build 時 element-ui 導入了不同的 vue core,錯誤產生了兩個不同的 vue instance,造成 el-table 吃不到專案的 context。
可透過 alias 配置,強制統一 vue 的引入目標。
// webpack
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm.js',
},
},
// vite
resolve: {
alias: {
vue: 'vue/dist/vue.esm.js',
},
},
element-ui 自訂 theme 被 umy-ui 搶 css 權重
我這專案同時使用 element-ui 與 umy-ui,都是全域引入該庫的 css。遷移到 vite 後卻發現 element-ui 的 class name 跟 umy-ui 撞名,自定義 theme 的 css 被 umy-ui 給搶權重。
研究半天發現,這兩個套件的 css 引入順序是這樣寫的。
import element-ui css
import custom element-ui theme sass
import umy-ui css
由於 umy-ui 最後才引入,必然它的權重是最強的。但由於 webpack 本身的 bug,錯誤將 Sass 文件最後才引入,所以在 webpack 環境下反而運行正常。
遷移到 vite 之後,只需調整正確的順序即可。
import element-ui css
import umy-ui css
import custom element-ui theme sass // change this
vite 中 template whitespace 間隔消失
這問題蠻瞎的,原本 webpack 環境下,把兩個 html <input> 放一起,渲染結果會有個小小的、類似 margin 效果的間隔。但遷移到 vite 之後卻消失了。
最初以為是 css 跑掉了,查了半天才發現是 template 編譯的問題……
<!-- source -->
<input />
<input />
<!-- webpack 編譯後 -->
<input /> <input />
<!-- vite 編譯後 -->
<input /><input />
Vue 的 template 本身是種模板引擎,跟 pug 那些一樣,會有 white space 的相關設定。
webpack 的 vue-loader 預設是將 line break 轉換成 space。而 vite 的 plugin-vue2 則會完全 minify。
可以透過設定 vue template 的 whitespace 還原。
// vite.config.js
plugins: [
vue({
template: {
compilerOptions: {
// 使 template 編譯保留空格
whitespace: 'preserve',
},
},
}),
],
ES6+ 語法出現 VScode ts 報錯
專案環境改變後,莫名其妙這一些 ES6+ 語法,在 VScode 中出現了紅線。
Object.entries()
// Property 'entries' does not exist on type 'ObjectConstructor'
async function foo() {}
// An async function or method in ES5/ES3 requires the 'Promise' constructor
排查後發現,是因為 VScode 將 ES+6 的語法拆成了不同的包,預設是不使用。需要在 jsconfig 或 tsconfig 添加 lib ESNext
設定。
// jsconfig.json
{
"compilerOptions": {
"lib": ["DOM", "DOM.Iterable", "ESNext"]
}
}
參考: