目的:項目投入使用發(fā)現(xiàn)很多使用起來不舒服的地方县踢,進行優(yōu)化
注意!!!:最新的一次創(chuàng)建項目運行時候以及配置eslint部分出現(xiàn)了許多問題
,可以結(jié)合最新的一篇vite+vue+ssg做官網(wǎng) 再記錄一下項目創(chuàng)建結(jié)合起來查看是否有你遇到的問題
前提:在上一篇vite + vue3多頁面配置記錄references,loadEnv等中我詳細記錄了通過各種配置了解多頁面項目瓷马。
結(jié)果:最終代碼放到gitee這里的release分支vite-vue3-multip-release
之前配置不合理的地方:
- 為了讓項目啟動的時候自動打開html,修改了項目根目錄到views下面
root:'./src/views/'
窜护,以至于outDir姨谷,windicss也要改康谆。- 所有生成的html全部扎堆生成在views下面,結(jié)構(gòu)混亂
- 未配置eslint嫉到,保存自動格式化
- 未配置代碼提交自動跑eslint檢測。使用
lint-staged + husky
- 未配置stylelint月洛,規(guī)范css書寫
- 未配置快速生成頁面腳本:用plop搞個模版生成index.vue和main.ts何恶,可以直接看代碼庫代碼
項目到實踐中肯定是不合理的,用起來不舒服嚼黔。逐步解決上面的問題
第一步:不修改根目錄路徑细层;在根目錄新建一個html文件夾,并將生成的html放到根目錄統(tǒng)一管理唬涧,且要支持多級頁面
通過上圖目錄結(jié)構(gòu)可以看到疫赎,src/views
下面有多級頁面,最后生成到src同級目錄下的html文件夾中碎节,且結(jié)構(gòu)與之對應(yīng)捧搞。這樣看起來就很舒服,html文件夾中的東西根本不用動狮荔,通過腳本胎撇,每次dev的時候自動生成
我們看代碼實現(xiàn),主要還是去修改build/getPage.ts
, 利用mkdirp生成多級文件夾
import glob from 'glob'
import fs from 'fs'
import mkdirp from 'mkdirp'
import { resolve } from 'path'
const input = {}
const mainEntry = []
const iconDirs = []
function getPages () {
// 遍歷文件夾中含有main.ts的文件夾路徑
const allEntry = glob.sync('./src/views/**/main.ts')
// console.log(allEntry)
// console.log('allEntry', allEntry)
// 創(chuàng)建多頁面模板
allEntry.forEach((entry: string) => {
const pathArr = entry.split('/')
const tsName = pathArr[pathArr.length - 2]
pathArr.pop()
const targetFilePath = pathArr.splice(3).join('/')
// 創(chuàng)建多級文件夾殖氏,去掉最后一個
const mkdirPath = targetFilePath.replace(`/${tsName}`, '')
const srcArr = entry.replace('./', '')
// console.log(targetFilePath, mkdirPath)
// 判斷文件是否存在
try {
fs.accessSync(`./html/${targetFilePath}.html`)
} catch (err) {
if (targetFilePath.includes('/')) {
mkdirp(`./html/${mkdirPath}`).then(() => {
generete(targetFilePath, srcArr)
})
} else {
generete(targetFilePath, srcArr)
}
}
const svgPath = srcArr.split('/')
svgPath.splice(svgPath.length - 1, 1)
// input中的配置
input[targetFilePath] = resolve(`html/${targetFilePath}.html`)
// vconsole用
mainEntry.push(resolve(`${srcArr}`))
iconDirs.push(resolve(process.cwd(), `${svgPath.join('/')}/svg`))
})
};
function generete (targetFilePath, srcArr) {
// 獲取模板
const temp = fs.readFileSync('./index.html')
// 多級相對路徑
let relativeStr = ''
targetFilePath.split('/').forEach(() => {
relativeStr += '../'
})
console.log(`創(chuàng)建${targetFilePath}.html文件`)
const index = temp.toString().indexOf('</body>')
const content =
temp.toString().slice(0, index) +
`<script type="module" src="${relativeStr}${srcArr}"></script>` +
temp.toString().slice(index)
fs.writeFile(`./html/${targetFilePath}.html`, content, err => {
if (err) console.log(err)
})
}
getPages()
// console.log(input, mainEntry, iconDirs)
export { input, mainEntry, iconDirs }
有了以上代碼晚树。每次運行都會根據(jù)入口main.ts,生成對應(yīng)的html雅采。但是啟動項目怎么直接打開我想要的index.html呢爵憎?
server里面有配置,配置open即可。想到當時僅僅為了啟動項目打開入口頁面就更改root是多么的不理智了
// vite.config.ts
server: {
open: '/html/index.html',
proxy: {
'/api': {
target: 'https://app-api-0.com',
changeOrigin: true
}
}
},
第二步:配置eslint
這個就比較簡單了婚瓜,網(wǎng)上也有很多教程宝鼓,當走到教程前面幾步就可以了。我這里也記錄一下
- 安裝eslint
npm i eslint -D
- 初始化配置:
npx eslint --init
然后根據(jù)提示一步步操作
2.1 選擇模式: (To check syntax and find problems)
我選第三個:To check syntax, find problems, and enforce code style
2.2 (選JavaScript modules): 選第一個:JavaScript modules (import/export)
2.3 選擇語言框架 (選Vue.js)
2.4 是否使用ts : 我這里選yes
2.5 代碼在哪里運行 (用空格選中 Browser+Node)
2.6 選擇一個風格:我選的Standard闰渔, 完全就夠用了
后面就是yes安裝席函,會發(fā)現(xiàn)安裝了這些插件
"eslint-config-standard": "^17.0.0",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-n": "^15.2.4",
"eslint-plugin-promise": "^6.0.0",
"eslint-plugin-vue": "^9.2.0",
"@typescript-eslint/eslint-plugin": "^5.30.7",
"@typescript-eslint/parser": "^5.30.7",
一些教程里面還單獨安裝@typescript-eslint/parser,我實踐中走完上面就已經(jīng)全部有了冈涧,生成的.eslintrc.js也不需要修改茂附。
只是部分規(guī)則不適用vue3,我們可以在rules直接關(guān)掉即可:比如 vue/multi-word-component-names, no-irregular-whitespace
3.選擇性安裝vite-plugin-eslint
, 用于配置vite運行的時候自動檢測eslint規(guī)范,使用npm run dev時會主動檢查代碼并報錯
npm i -D vite-plugin-eslint
使用
import eslint from 'vite-plugin-eslint'
export default defineConfig({
plugins: [
vue(),
eslint()
]
})
- setting.json 需要的內(nèi)容
// setting.json
{
// 重新設(shè)定tabsize
"editor.tabSize": 2,
// 每次保存的時候自動格式化
"editor.formatOnSave": false,
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
}
}
這里提一嘴i18n-ally
多語言翻譯這個vscode 插件督弓,好用手报。
// setting.json中加入
{
"i18n-ally.localesPaths": ["src/views/login/lang"],
"i18n-ally.keystyle": "nested",
"i18n-ally.sortKeys": true,
// pathMatcher 必需開啟namespace ,{locale}指的就是翻譯文件名"i18n-ally.localesPaths"往毡,{ext}就是enabledParsers中的文件后綴
"i18n-ally.namespace": true,
"i18n-ally.pathMatcher": "{locale}/{namespaces}.{ext}",
"i18n-ally.enabledParsers": ["js", "json", "ts"],
"i18n-ally.sourceLanguage": "en",
"i18n-ally.displayLanguage": "zh", // 展示中文
"i18n-ally.enabledFrameworks": ["vue", "react"],
}
主要提這個i18n-ally.pathMatcher路徑匹配踏揣,多份翻譯文件,放在在同一個二級文件src/lang/en
,src/lang/zh
夾就能通過它namespaces匹配到且生效
第三步:配置lint-staged + husky。在git commit 的時候?qū)μ峤晃募M行校驗
lint-staged工具對暫存的代碼進行 lint,通常都是配配合husky使用.
husky幫助你在git操作環(huán)節(jié)執(zhí)行l(wèi)int-staged录煤,也就是里面的 eslint --fix
對暫存的src
下面的文件進行eslint校驗鳄厌。
一般我們會看到如下package.json配置
//package.json
{
"lint-staged": {
"src/**/*.{js,jsx,ts,tsx,vue}": [
"eslint --fix" // 僅僅校驗修改暫存的文件
// "npm run lint:eslint". 如果要校驗所有文件的也可以,除非你想這么做
]
}
}
//"scripts": {
//"lint:eslint": "eslint --cache --max-warnings 0 \"{src,mock}/**/*.{vue,ts,js,tsx}\" --fix",
// }
通過husky安裝參考文檔可以發(fā)現(xiàn)妈踊,安裝husky有兩種方式了嚎,結(jié)果是一樣的
- 自動方式,只需要執(zhí)行一句
npx husky-init && npm install
npx husky-init && npm install # npm
npx husky-init && yarn # Yarn 1
yarn dlx husky-init --yarn2 && yarn # Yarn 2+
pnpm dlx husky-init && pnpm install # pnpm
執(zhí)行完后會在package.json/scripts 自動加上"prepare": "husky install"
廊营,
在根目錄生成了一個.husky文件夾歪泳,里面有個_pre-commit
腳本文件
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npm test
修改npm test
為自己的腳本命令,比如:npx lint-staged
這里的命令修改就可以自由發(fā)揮了露筒,只要能觸發(fā)package.json中的 lint-staged就成
比如我可以在這里寫npm run lint:lint-staged
,那package.json/scripts中有對應(yīng)的命令"lint:lint-staged": "lint-staged"
即可
tip:不走lint-staged呐伞,直接在這里寫npm run lint:eslint
也是可以的(lint:eslint
是scripts中的eslint --fix命令)。說明僅僅只安裝husky也是可以的慎式,那也就是校驗所有文件了伶氢。配合lint-staged只校驗暫存區(qū)文件才是最好的
- 手動方式,按照順序多執(zhí)行幾個命令
// 先安裝
npm i husky -D.
// 先執(zhí)行這句才能執(zhí)行有第四句
npx husky install
// 在package.json/scripts 加上`"prepare": "husky install"`瞬捕。自己手動去加也行
npm set-script prepare "husky install"
// 這句就是在`_pre-commit`腳本文件加上自己的命令啦
npx husky add .husky/pre-commit "npx lint-staged"
以上就能成功了鞍历。
第四步:配置stylelint
vscode 擴展必不可少:- 通過stylelint官方文檔我們先安裝三個插件:我項目用的less,多來一個
postcss-less
肪虎。如果你用scss劣砍,來一個postcss-scss
就好,下面配置一樣的
npm i stylelint stylelint-config-standard postcss-less -D
- 新建文件
.stylelintignore
/dist/*
/public/*
public/*
- 新建
.stylelintrc.js
扇救。stylelint默認只能識別css文件刑枝,我項目使用的less,上面安裝一個postcss-less
迅腔,使用官網(wǎng)提到的自定義語法customSyntax參數(shù)讓其能夠識別less文件装畅。
如果沒有下面配置的overrides/customSyntax
,less文件中會有看不懂的報錯:Unknown word (CssSyntaxError)Stylelint(CssSyntaxError)
// .stylelintrc.js
module.exports={
extends:["stylelint-config-standard",],
overrides:[
{
files:["**/*.less"],
customSyntax:"postcss-less"
}
]
}
- 有了上面的操作沧烈,已經(jīng)能看到less文件中的樣式各種紅色提示了掠兄,還需要保存自動格式化,在.vscode/setting.json中增加下面的內(nèi)容就可以了锌雀。
"editor.codeActionsOnSave": {
"source.fixAll.stylelint": true
}
- 項目是vue項目蚂夕,vue文件中的樣式無法識別,而且能看到輸出的報錯信息腋逆,提示我要
postcss-html
,安裝它
在.stylelintrc.js中加入它
module.exports={
extends:["stylelint-config-standard"],
customSyntax: "postcss-html",
overrides: [
{
files:["**/*.less"],
customSyntax:"postcss-less"
}
],
}
這時候你會發(fā)現(xiàn)vue文件中樣式并沒有提示問題婿牍。還差一步,在.vscode/settings.json
中增加
"stylelint.validate": ["vue", "less", "css"]
有了以上的簡單配置惩歉,就可以保存自動按照stylelint格式化你的樣式了
- 升級內(nèi)容
(1)結(jié)合lint-staged等脂,提交檢測樣式,在package.json中增加
"lint-staged": {
"**/*.{css,less,scss,vue}":[
"stylelint --fix"
]
}
(2)插件幫助我們css按照順序書寫
// 安裝插件
npm i -D stylelint-order stylelint-config-rational-order
stylelint-config-rational-order
插件用來簡化了插件stylelint-order
的引用和配置俏蛮。你只用stylelint-order
也是可以的
//.stylelintrc.js 中使用插件
module.exports={
extends:["stylelint-config-standard", 'stylelint-config-rational-order'],
}
下面是一些問題記錄
1. 當項目中使用了自動導(dǎo)入unplugin-auto-import/vite插件,eslint會提示ref等不存在
(1) 安裝 vue-global-api
(2) 在eslintrc.js中加入它
extends: [
'plugin:vue/vue3-essential',
'standard',
'vue-global-api'
],
2. 記錄一下cross-env上遥,cross-env 使用單個命令搏屑,而不用擔心環(huán)境變量的設(shè)置
安裝
npm i cross-env -D
使用
"report": "cross-env REPORT=true npm run build",
取參數(shù)
const isReport = process.env.REPORT === 'true'
isReport
? visualizer({
//生成的stats放到別的地方去
filename: './node_modules/.cache/visualizer/stats.html',
open: true,
gzipSize: true,
brotliSize: true
})
: [],
3. 項目中加入一個插件后,在linux編譯時莫名其妙報錯:Error: The package "esbuild-linux-64" could not be found, and is needed by esbuild.
If you are installing esbuild with npm, make sure that you don't specify the
"--no-optional" flag. The "optionalDependencies" package.json feature is used
by esbuild to install the correct binary executable for your current platform.
按照道理說jenkins工作區(qū)域的node_modules早就有了粉楚,怎么突然沒這個依賴了呢睬棚?
直接刪除工作區(qū)域代碼,重新npm i 跑一遍解決了
4. 該項目開發(fā)的多頁面是給安卓app用的解幼,用的lzyzsd/JsBridge。舊版app使用registerHandler提供native調(diào)用js的能力包警,在新版app失效撵摆,這個庫issue里面也提到了
直接將js方法掛到window下面,native去調(diào)用
// 該方法給安卓調(diào)用害晦,安卓返回是否開啟消息提醒
window.getPunchInReminderStatus = (res) => {
systemRemindOpen = res === '1'
}
5. window.onresize不觸發(fā)
舊版本安卓在進入頁面或者失去焦點的時候會觸發(fā)window.onresize特铝,當時使用它時為了控制fixed元素不被鍵盤頂起來。
在新版安卓中壹瘟,鍵盤并沒有將底部fixed元素頂起來鲫剿,且失去焦點的時候window.onresize不觸發(fā)了,用不上它了