perf: optimize for some details and comments (#4030)

* perf: optimize for some details and comments

* fix: test case

* chore: update ci
pull/48/MERGE
Vben 2024-08-04 05:42:59 +08:00 committed by GitHub
parent d3ed6757ac
commit b6415fad2d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
20 changed files with 37 additions and 134 deletions

View File

@ -44,6 +44,6 @@ jobs:
- name: Install dependencies - name: Install dependencies
run: pnpm install --frozen-lockfile run: pnpm install --frozen-lockfile
- name: Test and Build - name: Build
run: | run: |
pnpm run build pnpm run build

View File

@ -5,7 +5,6 @@ on:
push: push:
branches: branches:
- main - main
- master
- "releases/*" - "releases/*"
permissions: permissions:
@ -25,8 +24,8 @@ jobs:
node-version: [20] node-version: [20]
os: os:
- ubuntu-latest - ubuntu-latest
# - macos-latest - macos-latest
# - windows-latest - windows-latest
timeout-minutes: 20 timeout-minutes: 20
steps: steps:
- name: Checkout code - name: Checkout code

View File

@ -9,17 +9,18 @@ on:
jobs: jobs:
main: main:
if: github.repository == 'vitejs/vite'
runs-on: ubuntu-latest runs-on: ubuntu-latest
name: Semantic Pull Request name: Semantic Pull Request
steps: steps:
- name: Validate PR title - name: Validate PR title
uses: amannn/action-semantic-pull-request@v5 uses: amannn/action-semantic-pull-request@v5
with: with:
wip: true
subjectPattern: ^(?![A-Z]).+$ subjectPattern: ^(?![A-Z]).+$
subjectPatternError: | subjectPatternError: |
The subject "{subject}" found in the pull request title "{title}" The subject "{subject}" found in the pull request title "{title}"
didn't match the configured pattern. Please ensure that the subject didn't match the configured pattern. Please ensure that the subject
doesn't start with an uppercase character. doesn't start with an uppercase character.
requireScope: false
env: env:
GITHUB_TOKEN: ${{ secrets.ACCESS_TOKEN }} GITHUB_TOKEN: ${{ secrets.ACCESS_TOKEN }}

View File

@ -1,87 +0,0 @@
#user nobody;
worker_processes 1;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
types {
application/javascript js mjs;
text/css css;
text/html html;
}
sendfile on;
# tcp_nopush on;
#keepalive_timeout 0;
# keepalive_timeout 65;
# gzip on;
# gzip_buffers 32 16k;
# gzip_comp_level 6;
# gzip_min_length 1k;
# gzip_static on;
# gzip_types text/plain
# text/css
# application/javascript
# application/json
# application/x-javascript
# text/xml
# application/xml
# application/xml+rss
# text/javascript; #设置压缩的文件类型
# gzip_vary on;
server {
listen 8080;
server_name localhost;
location / {
root /usr/share/nginx/html;
try_files $uri $uri/ /index.html;
index index.html;
# Enable CORS
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain charset=UTF-8';
add_header 'Content-Length' 0;
return 204;
}
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
}
# stream { # stream 模块配置和 http 模块在相同级别
# upstream redis {
# server 127.0.0.1:6379 max_fails=3 fail_timeout=30s;
# }
# server {
# listen 16379;
# proxy_connect_timeout 1s;
# proxy_timeout 3s;
# proxy_pass redis;
# }
# }

View File

@ -6,7 +6,7 @@
## 原理 ## 原理
`vite-plugin-inject-app-loading` 插件实现,插件会在每个页面的注入一个全局的 loading html `vite-plugin-inject-app-loading` 插件实现,插件会在每个应用的注入一个全局的 `loading html`
## 关闭 ## 关闭

View File

@ -47,7 +47,6 @@ const userConfig = {
defaultScope: scopeComplete, defaultScope: scopeComplete,
// English // English
typesAppend: [ typesAppend: [
{ name: 'wip: work in process', value: 'wip' },
{ name: 'workflow: workflow improvements', value: 'workflow' }, { name: 'workflow: workflow improvements', value: 'workflow' },
{ name: 'types: type definition file changes', value: 'types' }, { name: 'types: type definition file changes', value: 'types' },
], ],
@ -122,7 +121,7 @@ const userConfig = {
'header-max-length': [2, 'always', 108], 'header-max-length': [2, 'always', 108],
'scope-enum': [0], 'scope-enum': [0],
'subject-case': [0], 'subject-case': [2, 'always', 'lower-case'],
'subject-empty': [2, 'never'], 'subject-empty': [2, 'never'],
'type-empty': [2, 'never'], 'type-empty': [2, 'never'],
/** /**

View File

@ -15,8 +15,8 @@ import { getCommonConfig } from './common';
function defineApplicationConfig(userConfigPromise?: DefineApplicationOptions) { function defineApplicationConfig(userConfigPromise?: DefineApplicationOptions) {
return defineConfig(async (config) => { return defineConfig(async (config) => {
const { appTitle, base, port, ...envConfig } = await loadAndConvertEnv();
const options = await userConfigPromise?.(config); const options = await userConfigPromise?.(config);
const { appTitle, base, port, ...envConfig } = await loadAndConvertEnv();
const { command, mode } = config; const { command, mode } = config;
const { application = {}, vite = {} } = options || {}; const { application = {}, vite = {} } = options || {};
const root = process.cwd(); const root = process.cwd();
@ -78,16 +78,16 @@ function defineApplicationConfig(userConfigPromise?: DefineApplicationOptions) {
port, port,
warmup: { warmup: {
// 预热文件 // 预热文件
clientFiles: ['./index.html', './src/{views,layouts}/*'], clientFiles: ['./index.html', './src/{views,layouts,router,store}/*'],
}, },
}, },
}; };
const mergedConfig = mergeConfig( const mergedCommonConfig = mergeConfig(
await getCommonConfig(), await getCommonConfig(),
applicationConfig, applicationConfig,
); );
return mergeConfig(mergedConfig, vite); return mergeConfig(mergedCommonConfig, vite);
}); });
} }

View File

@ -13,8 +13,8 @@ function defineLibraryConfig(userConfigPromise?: DefineLibraryOptions) {
return defineConfig(async (config: ConfigEnv) => { return defineConfig(async (config: ConfigEnv) => {
const options = await userConfigPromise?.(config); const options = await userConfigPromise?.(config);
const { command, mode } = config; const { command, mode } = config;
const root = process.cwd();
const { library = {}, vite = {} } = options || {}; const { library = {}, vite = {} } = options || {};
const root = process.cwd();
const isBuild = command === 'build'; const isBuild = command === 'build';
const plugins = await loadLibraryPlugins({ const plugins = await loadLibraryPlugins({
@ -52,8 +52,8 @@ function defineLibraryConfig(userConfigPromise?: DefineLibraryOptions) {
plugins, plugins,
}; };
const commonConfig = await getCommonConfig(); const commonConfig = await getCommonConfig();
const mergedConfig = mergeConfig(commonConfig, packageConfig); const mergedConmonConfig = mergeConfig(commonConfig, packageConfig);
return mergeConfig(mergedConfig, vite); return mergeConfig(mergedConmonConfig, vite);
}); });
} }

View File

@ -28,12 +28,12 @@ const getDefaultPwaOptions = (name: string): Partial<PwaPluginOptions> => ({
const defaultImportmapOptions: ImportmapPluginOptions = { const defaultImportmapOptions: ImportmapPluginOptions = {
// 通过 Importmap CDN 方式引入, // 通过 Importmap CDN 方式引入,
// 目前只有esm.sh源兼容性好一点jspm.io对于 esm 入口要求高 // 目前只有esm.sh源兼容性好一点jspm.io对于 esm 入口要求高
defaultProvider: 'jspm.io', defaultProvider: 'esm.sh',
importmap: [ importmap: [
{ name: 'vue' }, { name: 'vue' },
{ name: 'pinia' }, { name: 'pinia' },
{ name: 'vue-router' }, { name: 'vue-router' },
{ name: 'vue-i18n' }, // { name: 'vue-i18n' },
{ name: 'dayjs' }, { name: 'dayjs' },
{ name: 'vue-demi' }, { name: 'vue-demi' },
], ],

View File

@ -1,3 +1,3 @@
# inject-app-loading # inject-app-loading
用于在应用加载时显示加载动画的插件可自行选择加载动画的样式。 用于在应用加载时显示加载动画的插件可自行选择加载动画的样式。

View File

@ -25,7 +25,7 @@
pointer-events: none; pointer-events: none;
visibility: hidden; visibility: hidden;
opacity: 0; opacity: 0;
transition: all 0.6s ease-out; transition: all 1s ease-out;
} }
.dark .loading { .dark .loading {

View File

@ -52,19 +52,15 @@ async function viteInjectAppLoadingPlugin(
* loadinghtml * loadinghtml
*/ */
async function getLoadingRawByHtmlTemplate(loadingTemplate: string) { async function getLoadingRawByHtmlTemplate(loadingTemplate: string) {
const __dirname = fileURLToPath(new URL('.', import.meta.url));
const defaultLoadingPath = join(__dirname, './default-loading.html');
// 支持在app内自定义loading模板模版参考default-loading.html即可 // 支持在app内自定义loading模板模版参考default-loading.html即可
const appLoadingPath = join(process.cwd(), loadingTemplate); let appLoadingPath = join(process.cwd(), loadingTemplate);
let loadingPath = defaultLoadingPath;
if (fs.existsSync(appLoadingPath)) { if (!fs.existsSync(appLoadingPath)) {
loadingPath = appLoadingPath; const __dirname = fileURLToPath(new URL('.', import.meta.url));
return; appLoadingPath = join(__dirname, './default-loading.html');
} }
const htmlRaw = await fsp.readFile(loadingPath, 'utf8'); return await fsp.readFile(appLoadingPath, 'utf8');
return htmlRaw;
} }
export { viteInjectAppLoadingPlugin }; export { viteInjectAppLoadingPlugin };

View File

@ -74,13 +74,13 @@ interface CommonPluginOptions {
} }
interface ApplicationPluginOptions extends CommonPluginOptions { interface ApplicationPluginOptions extends CommonPluginOptions {
/** 开启 gzip 压缩 */ /** 开启 gzip|brotli 压缩 */
compress?: boolean; compress?: boolean;
/** 压缩类型 */ /** 压缩类型 */
compressTypes?: ('brotli' | 'gzip')[]; compressTypes?: ('brotli' | 'gzip')[];
/** 在构建的时候抽离配置文件 */ /** 在构建的时候抽离配置文件 */
extraAppConfig?: boolean; extraAppConfig?: boolean;
/** html 插件配置 */ /** 是否开启html插件 */
html?: boolean; html?: boolean;
/** 是否开启i18n */ /** 是否开启i18n */
i18n?: boolean; i18n?: boolean;
@ -98,7 +98,7 @@ interface ApplicationPluginOptions extends CommonPluginOptions {
nitroMock?: boolean; nitroMock?: boolean;
/** nitro mock 插件配置 */ /** nitro mock 插件配置 */
nitroMockOptions?: NitroMockPluginOptions; nitroMockOptions?: NitroMockPluginOptions;
/** dev是否开启mock服务 */ /** 开启控制台自定义打印 */
print?: boolean; print?: boolean;
/** 打印插件配置 */ /** 打印插件配置 */
printInfoMap?: PrintPluginOptions['infoMap']; printInfoMap?: PrintPluginOptions['infoMap'];

View File

@ -1,7 +1,8 @@
import { beforeEach, describe, expect, it, vi } from 'vitest'; import { beforeEach, describe, expect, it, vi } from 'vitest';
import { defaultPreferences } from './config'; import { defaultPreferences } from './config';
import { isDarkTheme, PreferenceManager } from './preferences'; import { PreferenceManager } from './preferences';
import { isDarkTheme } from './update-css-variables';
describe('preferences', () => { describe('preferences', () => {
let preferenceManager: PreferenceManager; let preferenceManager: PreferenceManager;

View File

@ -19,14 +19,6 @@ const STORAGE_KEY = 'preferences';
const STORAGE_KEY_LOCALE = `${STORAGE_KEY}-locale`; const STORAGE_KEY_LOCALE = `${STORAGE_KEY}-locale`;
const STORAGE_KEY_THEME = `${STORAGE_KEY}-theme`; const STORAGE_KEY_THEME = `${STORAGE_KEY}-theme`;
function isDarkTheme(theme: string) {
let dark = theme === 'dark';
if (theme === 'auto') {
dark = window.matchMedia('(prefers-color-scheme: dark)').matches;
}
return dark;
}
class PreferenceManager { class PreferenceManager {
private cache: null | StorageManager = null; private cache: null | StorageManager = null;
// private flattenedState: Flatten<Preferences>; // private flattenedState: Flatten<Preferences>;
@ -39,6 +31,7 @@ class PreferenceManager {
constructor() { constructor() {
this.cache = new StorageManager(); this.cache = new StorageManager();
// 避免频繁的操作缓存
this.savePreferences = useDebounceFn( this.savePreferences = useDebounceFn(
(preference: Preferences) => this._savePreferences(preference), (preference: Preferences) => this._savePreferences(preference),
150, 150,
@ -58,7 +51,6 @@ class PreferenceManager {
/** /**
* *
* *
*
* @param {DeepPartial<Preferences>} updates - * @param {DeepPartial<Preferences>} updates -
*/ */
private handleUpdates(updates: DeepPartial<Preferences>) { private handleUpdates(updates: DeepPartial<Preferences>) {
@ -124,7 +116,7 @@ class PreferenceManager {
this.updatePreferences({ this.updatePreferences({
theme: { mode: isDark ? 'dark' : 'light' }, theme: { mode: isDark ? 'dark' : 'light' },
}); });
updateCSSVariables(this.state); // updateCSSVariables(this.state);
}); });
} }
@ -232,4 +224,4 @@ class PreferenceManager {
} }
const preferencesManager = new PreferenceManager(); const preferencesManager = new PreferenceManager();
export { isDarkTheme, PreferenceManager, preferencesManager }; export { PreferenceManager, preferencesManager };

View File

@ -115,4 +115,4 @@ function isDarkTheme(theme: string) {
return dark; return dark;
} }
export { updateCSSVariables }; export { isDarkTheme, updateCSSVariables };

View File

@ -2,7 +2,8 @@ import { computed } from 'vue';
import { diff } from '@vben-core/shared'; import { diff } from '@vben-core/shared';
import { isDarkTheme, preferencesManager } from './preferences'; import { preferencesManager } from './preferences';
import { isDarkTheme } from './update-css-variables';
function usePreferences() { function usePreferences() {
const preferences = preferencesManager.getPreferences(); const preferences = preferencesManager.getPreferences();

View File

@ -209,7 +209,7 @@ export function useElementPlusDesignTokens() {
'--el-text-color-primary': getCssVariableValue('--foreground'), '--el-text-color-primary': getCssVariableValue('--foreground'),
'--el-text-color-regular': getCssVariableValue('--foreground'), '--el-text-color-regular': getCssVariableValue('--foreground'),
}; };
updateCSSVariables(variables, `__vben_ele_styles__`); updateCSSVariables(variables, `__vben_design_styles__`);
}, },
{ immediate: true }, { immediate: true },
); );

View File

@ -3,6 +3,7 @@
* index.html app * index.html app
* cssloading * cssloading
* *
* loadinghttps://doc.vben.pro/guide/in-depth/loading.html
*/ */
export function unmountGlobalLoading() { export function unmountGlobalLoading() {
// 查找全局 loading 元素 // 查找全局 loading 元素

View File

@ -20,7 +20,7 @@ export async function run(options: RunOptions) {
// 只显示有对应命令的包 // 只显示有对应命令的包
const selectPkgs = packages.filter((pkg) => { const selectPkgs = packages.filter((pkg) => {
return (pkg?.packageJson as Record<string, any>).scripts?.[command]; return (pkg?.packageJson as Record<string, any>)?.scripts?.[command];
}); });
const selectPkg = await select<any, string>({ const selectPkg = await select<any, string>({