├── .dockerignore ├── env.d.ts ├── .env.test ├── .env.development ├── public └── favicon.ico ├── src ├── assets │ ├── main.css │ ├── logo.svg │ ├── icons │ │ └── github.svg │ └── base.css ├── App.vue ├── main.ts └── components │ └── Welcome.vue ├── scripts ├── vars.mjs ├── git.mjs ├── version.mjs ├── changelog.mjs ├── docker.mjs └── build.mjs ├── .vscode └── extensions.json ├── .env.production ├── Dockerfile-test ├── Dockerfile-development ├── .prettierrc.json ├── Dockerfile-production ├── nginx.test.conf ├── nginx.development.conf ├── nginx.production.conf ├── CHANGELOG.md ├── tsconfig.json ├── tsconfig.vitest.json ├── index.html ├── .eslintrc.cjs ├── tsconfig.app.json ├── tsconfig.node.json ├── .gitignore ├── uno.config.ts ├── README.md ├── package.json ├── .github └── workflows │ └── deploy.yaml └── vite.config.ts /.dockerignore: -------------------------------------------------------------------------------- 1 | .github 2 | .vscode 3 | node_modules -------------------------------------------------------------------------------- /env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /.env.test: -------------------------------------------------------------------------------- 1 | #是否移除控制台 2 | VITE_DROP_CONSOLE=false 3 | # 网站前缀 4 | VITE_BASE_URL=/ -------------------------------------------------------------------------------- /.env.development: -------------------------------------------------------------------------------- 1 | #是否移除控制台 2 | VITE_DROP_CONSOLE=false 3 | # 网站前缀 4 | VITE_BASE_URL=/ 5 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zerotower69/demo-template/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /src/assets/main.css: -------------------------------------------------------------------------------- 1 | @import './base.css'; 2 | 3 | #app{ 4 | height: 100%; 5 | width: 100%; 6 | } 7 | -------------------------------------------------------------------------------- /scripts/vars.mjs: -------------------------------------------------------------------------------- 1 | import path from 'path' 2 | 3 | export const CMD = process.cwd() 4 | 5 | export const PKG_PATH = path.resolve(CMD,'package.json') 6 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "Vue.volar", 4 | "dbaeumer.vscode-eslint", 5 | "esbenp.prettier-vscode" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 8 | 9 | -------------------------------------------------------------------------------- /.env.production: -------------------------------------------------------------------------------- 1 | #是否移除控制台 2 | VITE_DROP_CONSOLE=true 3 | # 网站前缀 按github部署仓库名修改 4 | # 如果仓库名是 scroll-image,则 5 | # VITE_BASE_URL=/scroll-image/ 6 | VITE_BASE_URL=/ 7 | -------------------------------------------------------------------------------- /Dockerfile-test: -------------------------------------------------------------------------------- 1 | FROM nginx:stable-alpine 2 | 3 | WORKDIR /app 4 | 5 | COPY dist /usr/share/nginx/html/web 6 | COPY ./nginx.test.conf /etc/nginx/conf.d/default.conf 7 | 8 | EXPOSE 80 -------------------------------------------------------------------------------- /Dockerfile-development: -------------------------------------------------------------------------------- 1 | FROM nginx:stable-alpine 2 | 3 | WORKDIR /app 4 | 5 | COPY dist /usr/share/nginx/html/web 6 | COPY ./nginx.develpment.conf /etc/nginx/conf.d/default.conf 7 | 8 | EXPOSE 80 -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import './assets/main.css' 2 | 3 | import { createApp } from 'vue' 4 | import App from './App.vue' 5 | import "virtual:uno.css" 6 | 7 | const app=createApp(App) 8 | app.mount('#app') 9 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/prettierrc", 3 | "semi": false, 4 | "tabWidth": 2, 5 | "singleQuote": true, 6 | "printWidth": 100, 7 | "trailingComma": "none" 8 | } -------------------------------------------------------------------------------- /Dockerfile-production: -------------------------------------------------------------------------------- 1 | FROM nginx:stable-alpine 2 | 3 | WORKDIR /app 4 | 5 | COPY dist /usr/share/nginx/html/web 6 | COPY ./nginx.production.conf /etc/nginx/conf.d/default.conf 7 | 8 | EXPOSE 80 9 | 10 | 11 | -------------------------------------------------------------------------------- /nginx.test.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80; 3 | server_name localhost; 4 | 5 | location / { 6 | root /usr/share/nginx/html/web; 7 | index index.html; 8 | try_files $uri /index.html; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /nginx.development.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80; 3 | server_name localhost; 4 | 5 | location / { 6 | root /usr/share/nginx/html/web; 7 | index index.html; 8 | try_files $uri /index.html; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /nginx.production.conf: -------------------------------------------------------------------------------- 1 | server { 2 | listen 80; 3 | server_name localhost; 4 | 5 | location / { 6 | root /usr/share/nginx/html/web; 7 | index index.html; 8 | try_files $uri /index.html; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # 更新日志 2 | 3 | ## 1.0.0 (2024-05-25 14:28) 4 | 5 | Y 6 | # 更新日志 7 | 8 | ## 1.0.0 (2024-05-25 14:42) 9 | 10 | feat: vue3模板初步创建完成 11 | # 更新日志 12 | 13 | ## 0.1.0 (2024-05-25 14:13) 14 | 15 | feat: vue3模板初步创建完成 16 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [], 3 | "references": [ 4 | { 5 | "path": "./tsconfig.node.json" 6 | }, 7 | { 8 | "path": "./tsconfig.app.json" 9 | }, 10 | { 11 | "path": "./tsconfig.vitest.json" 12 | } 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /src/assets/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /tsconfig.vitest.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.app.json", 3 | "exclude": [], 4 | "compilerOptions": { 5 | "composite": true, 6 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.vitest.tsbuildinfo", 7 | 8 | "lib": [], 9 | "types": ["node", "jsdom"] 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | <%- title %> 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | /* eslint-env node */ 2 | require('@rushstack/eslint-patch/modern-module-resolution') 3 | 4 | module.exports = { 5 | root: true, 6 | 'extends': [ 7 | 'plugin:vue/vue3-essential', 8 | 'eslint:recommended', 9 | '@vue/eslint-config-typescript', 10 | '@vue/eslint-config-prettier/skip-formatting' 11 | ], 12 | parserOptions: { 13 | ecmaVersion: 'latest' 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@vue/tsconfig/tsconfig.dom.json", 3 | "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], 4 | "exclude": ["src/**/__tests__/*"], 5 | "compilerOptions": { 6 | "composite": true, 7 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", 8 | 9 | "baseUrl": ".", 10 | "paths": { 11 | "@/*": ["./src/*"] 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@tsconfig/node20/tsconfig.json", 3 | "include": [ 4 | "vite.config.*", 5 | "cypress.config.*", 6 | "nightwatch.conf.*", 7 | "playwright.config.*" 8 | ], 9 | "compilerOptions": { 10 | "composite": true, 11 | "noEmit": true, 12 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", 13 | 14 | "module": "ESNext", 15 | "moduleResolution": "Bundler", 16 | "types": ["node"] 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | .DS_Store 12 | dist 13 | output 14 | docker 15 | dist-ssr 16 | coverage 17 | *.local 18 | 19 | /cypress/videos/ 20 | /cypress/screenshots/ 21 | 22 | # Editor directories and files 23 | .vscode/* 24 | !.vscode/extensions.json 25 | .idea 26 | *.suo 27 | *.ntvs* 28 | *.njsproj 29 | *.sln 30 | *.sw? 31 | 32 | *.tsbuildinfo 33 | .env.local 34 | -------------------------------------------------------------------------------- /uno.config.ts: -------------------------------------------------------------------------------- 1 | import {defineConfig,presetIcons,presetAttributify,presetUno} from "unocss" 2 | import {FileSystemIconLoader} from "@iconify/utils/lib/loader/node-loaders" 3 | 4 | export default defineConfig({ 5 | presets:[ 6 | presetUno({}), 7 | presetAttributify({}), 8 | presetIcons({ 9 | collections:{ 10 | custom: 11 | FileSystemIconLoader('./src/assets/icons', 12 | svg => svg.replace(/#fff/, 'currentColor')) 13 | } 14 | }) 15 | ] 16 | }) -------------------------------------------------------------------------------- /src/components/Welcome.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | 11 | 12 | 24 | -------------------------------------------------------------------------------- /scripts/git.mjs: -------------------------------------------------------------------------------- 1 | import {execSync} from "child_process" 2 | import dayjs from 'dayjs' 3 | 4 | //get git user 5 | export function getGitUser(){ 6 | return execSync('git config user.name').toString('utf8') 7 | } 8 | 9 | /** 10 | * get current info 11 | * @return {{date: string, author: string, id: string, message: string, email: string}} 12 | */ 13 | export function getCurrentCommitInfo(){ 14 | const message = execSync(`git log -1 --pretty=format:"%H#%s#%an#%ad#%ae"`).toString('utf8') 15 | const list = message.split('#') 16 | return { 17 | id: list[0], 18 | message:list[1], 19 | author:list[2], 20 | date:dayjs(list[3]).format('YYYY-MM-DD HH:mm:ss'), 21 | email:list[4] 22 | } 23 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vue3 示例模板 2 | 3 | > vue3快速模板,引入了unocss支持快速示例搭建,并提供完善的打包配置。 4 | 5 | ## 安装依赖 6 | 7 | **项目node版本16起步,如果低于该版本,请考虑使用nvm升级** 8 | 9 | ```bash 10 | npm install 11 | ``` 12 | 13 | ## 项目运行 14 | 15 | ```bash 16 | npm run dev 17 | ``` 18 | 19 | ## 打包 20 | 21 | ```bash 22 | npm run build #普通打包,会检查ts和eslint错误 23 | npm run build-only #普通打包,不会检查ts错误 24 | npm run build:docker 25 | ``` 26 | 27 | ## 配置文件 28 | 29 | 可以前往[.dev.production](/.env.production)文件查看,你可以按注释提示修改 30 | 相关的VITE_ 应用变量来完成相应的应用标题,部署路径的更改 31 | 32 | ## 工作流 33 | 34 | 可以将项目快速部署到github pages,因此你需要注意工作流中使用的node版本和pnpm版本是否和 35 | [package.json](package.json)中一致。如果你的项目输出目录更改后(默认是dist), 36 | 对应[deploy.yaml](.github/workflows/deploy.yaml)文件的部署路径也需要相应地更改。 37 | 38 | ## 其它 39 | 使用上有问题请提issues。 40 | -------------------------------------------------------------------------------- /scripts/version.mjs: -------------------------------------------------------------------------------- 1 | import fs from "fs" 2 | import {PKG_PATH,CMD} from "./vars.mjs" 3 | import semver from "semver" 4 | 5 | /** 6 | * get package.json info 7 | * @return {Record} 8 | */ 9 | export function getPKG(){ 10 | const text=fs.readFileSync(PKG_PATH,'utf8'); 11 | return JSON.parse(text) 12 | } 13 | 14 | /** 15 | * get app version 16 | * @return {string} 17 | */ 18 | export function getVersion(){ 19 | return process.env['npm_package_version'] 20 | } 21 | 22 | /** 23 | * set app version 24 | * @param {string} version 25 | * @return boolean 26 | */ 27 | export function setVersion(version){ 28 | try{ 29 | const pkg = getPKG(); 30 | pkg.version = version; 31 | fs.writeFileSync(PKG_PATH,JSON.stringify(pkg,null,2)) 32 | return true 33 | } catch (e){ 34 | return false 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /scripts/changelog.mjs: -------------------------------------------------------------------------------- 1 | import path from 'path' 2 | import {CMD} from "./vars.mjs" 3 | import fs from 'fs' 4 | import dayjs from 'dayjs' 5 | import { getCurrentCommitInfo } from './git.mjs' 6 | 7 | const CHANGELOG_PATH = path.resolve(CMD,'CHANGELOG.md') 8 | 9 | /** 10 | * 11 | * @param {{version:string,startTime:number,message:string}} info 12 | */ 13 | export function writeChangelog(info){ 14 | const originContent = fs.readFileSync(CHANGELOG_PATH,{encoding:'utf8'}) 15 | const time = dayjs(info.startTime).format('YYYY-MM-DD HH:ss') 16 | //info 17 | const title = `\n\n## ${info.version} (${time})` 18 | const gitInfo = getCurrentCommitInfo(); 19 | let content = `\n\n${info.message}` 20 | content=title+content 21 | content = '# 更新日志'+content+"\n"+originContent 22 | fs.writeFileSync(CHANGELOG_PATH,content,{encoding:'utf8'}) 23 | } -------------------------------------------------------------------------------- /scripts/docker.mjs: -------------------------------------------------------------------------------- 1 | import os from 'os' 2 | import {execSync} from "child_process" 3 | import fs from 'fs' 4 | import path from 'path' 5 | import { CMD } from './vars.mjs' 6 | 7 | /** 8 | * docker command exit 9 | * @return {boolean} 10 | */ 11 | export function exitDocker(){ 12 | const platform=os.platform() 13 | const command = platform ==='win32' ? 'where docker':'which docker' 14 | try{ 15 | execSync(command).toString('utf8') 16 | return true 17 | } catch (e){ 18 | return false 19 | } 20 | } 21 | 22 | /** 23 | * 24 | * @param {string} filepath 25 | */ 26 | export function checkConfigPath(filepath){ 27 | return fs.existsSync(path.resolve(CMD,filepath)) 28 | } 29 | 30 | /** 31 | * check docker deamon 32 | * @return {boolean} 33 | */ 34 | export function dockerIsRunning(){ 35 | try{ 36 | execSync('docker info') 37 | return true 38 | } catch (e){ 39 | return false 40 | } 41 | } 42 | 43 | export function beforeValidate(){ 44 | 45 | } 46 | 47 | /** 48 | * 49 | * @param {string} name 50 | */ 51 | export function buildImage(name){ 52 | try{ 53 | execSync(`docker ps -q --filter ancestor=${name}`) 54 | } catch (e){ 55 | 56 | } 57 | } -------------------------------------------------------------------------------- /src/assets/icons/github.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue3-demo", 3 | "version": "1.0.0", 4 | "private": true, 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "preview": "vite preview", 9 | "build": "node scripts/build.mjs", 10 | "test:unit": "vitest", 11 | "build-only": "vite build", 12 | "type-check": "vue-tsc --build --force", 13 | "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore", 14 | "format": "prettier --write src/" 15 | }, 16 | "dependencies": { 17 | "dayjs": "^1.11.11", 18 | "vue": "^3.4.21" 19 | }, 20 | "devDependencies": { 21 | "@iconify/utils": "^2.1.23", 22 | "@rushstack/eslint-patch": "^1.8.0", 23 | "@tsconfig/node20": "^20.1.4", 24 | "@types/consola": "^2.2.5", 25 | "@types/inquirer": "^9.0.7", 26 | "@types/jsdom": "^21.1.6", 27 | "@types/node": "^20.12.5", 28 | "@vitejs/plugin-legacy": "^5.4.0", 29 | "@vitejs/plugin-vue": "^5.0.4", 30 | "@vitejs/plugin-vue-jsx": "^3.1.0", 31 | "@vue/eslint-config-prettier": "^9.0.0", 32 | "@vue/eslint-config-typescript": "^13.0.0", 33 | "@vue/test-utils": "^2.4.5", 34 | "@vue/tsconfig": "^0.5.1", 35 | "chalk": "^5.3.0", 36 | "consola": "^3.2.3", 37 | "eslint": "^8.57.0", 38 | "eslint-plugin-vue": "^9.23.0", 39 | "inquirer": "^9.2.22", 40 | "jsdom": "^24.0.0", 41 | "npm-run-all2": "^6.1.2", 42 | "prettier": "^3.2.5", 43 | "semver": "^7.6.2", 44 | "typescript": "~5.4.0", 45 | "unocss": "^0.60.2", 46 | "vite": "^5.2.8", 47 | "vite-plugin-html": "^3.2.2", 48 | "vite-plugin-progress": "^0.0.7", 49 | "vite-plugin-vue-devtools": "^7.0.25", 50 | "vitest": "^1.4.0", 51 | "vue-tsc": "^2.0.11" 52 | } 53 | } -------------------------------------------------------------------------------- /src/assets/base.css: -------------------------------------------------------------------------------- 1 | /* color palette from */ 2 | :root { 3 | --vt-c-white: #ffffff; 4 | --vt-c-white-soft: #f8f8f8; 5 | --vt-c-white-mute: #f2f2f2; 6 | 7 | --vt-c-black: #181818; 8 | --vt-c-black-soft: #222222; 9 | --vt-c-black-mute: #282828; 10 | 11 | --vt-c-indigo: #2c3e50; 12 | 13 | --vt-c-divider-light-1: rgba(60, 60, 60, 0.29); 14 | --vt-c-divider-light-2: rgba(60, 60, 60, 0.12); 15 | --vt-c-divider-dark-1: rgba(84, 84, 84, 0.65); 16 | --vt-c-divider-dark-2: rgba(84, 84, 84, 0.48); 17 | 18 | --vt-c-text-light-1: var(--vt-c-indigo); 19 | --vt-c-text-light-2: rgba(60, 60, 60, 0.66); 20 | --vt-c-text-dark-1: var(--vt-c-white); 21 | --vt-c-text-dark-2: rgba(235, 235, 235, 0.64); 22 | } 23 | 24 | /* semantic color variables for this project */ 25 | :root { 26 | --color-background: var(--vt-c-white); 27 | --color-background-soft: var(--vt-c-white-soft); 28 | --color-background-mute: var(--vt-c-white-mute); 29 | 30 | --color-border: var(--vt-c-divider-light-2); 31 | --color-border-hover: var(--vt-c-divider-light-1); 32 | 33 | --color-heading: var(--vt-c-text-light-1); 34 | --color-text: var(--vt-c-text-light-1); 35 | 36 | --section-gap: 160px; 37 | } 38 | 39 | @media (prefers-color-scheme: dark) { 40 | :root { 41 | --color-background: var(--vt-c-black); 42 | --color-background-soft: var(--vt-c-black-soft); 43 | --color-background-mute: var(--vt-c-black-mute); 44 | 45 | --color-border: var(--vt-c-divider-dark-2); 46 | --color-border-hover: var(--vt-c-divider-dark-1); 47 | 48 | --color-heading: var(--vt-c-text-dark-1); 49 | --color-text: var(--vt-c-text-dark-2); 50 | } 51 | } 52 | 53 | *, 54 | *::before, 55 | *::after { 56 | box-sizing: border-box; 57 | margin: 0; 58 | padding: 0; 59 | font-weight: normal; 60 | } 61 | 62 | html,body{ 63 | height: 100%; 64 | width: 100%; 65 | } 66 | 67 | -------------------------------------------------------------------------------- /.github/workflows/deploy.yaml: -------------------------------------------------------------------------------- 1 | # 1. 为工作流定义名字 2 | name: Build for scroll-image 3 | 4 | # 2. 触发条件修改为: 当 指定的分支, 有 push 的时候, 执行任务 5 | on: 6 | push: 7 | branches: 8 | # 当代码被推送到这个分支时触发相应的工作流 9 | - gh-pages 10 | # 这个选项可以使你手动在 Action tab 页面触发工作流 11 | workflow_dispatch: 12 | 13 | # 设置 GITHUB_TOKEN 的权限,以允许部署到 GitHub Pages。 14 | permissions: 15 | contents: read 16 | pages: write 17 | id-token: write 18 | 19 | # 允许一个并发的部署 20 | concurrency: 21 | group: 'pages' 22 | cancel-in-progress: true 23 | 24 | # 3. 创建工作流 25 | jobs: 26 | deploy: #单次部署的工作描述 27 | # Deploy to the github-pages environment 28 | environment: 29 | name: github-pages 30 | url: ${{ steps.deployment.outputs.page_url }} 31 | runs-on: ubuntu-latest # 依赖环境 32 | 33 | steps: # 工作流步骤 34 | # step 1. 获取源码, 拉取仓库代码 35 | - name: Checkout 🛎️ # 步骤名 36 | uses: actions/checkout@v3 # 使用插件 => https://github.com/actions/checkout 37 | 38 | # step 2. 使用指定版本 node 39 | - name: Use Node 📦 # 步骤名 40 | uses: actions/setup-node@v3 # 使用插件 => https://github.com/actions/setup-node 41 | with: # 插件携带参数 42 | # 记得按最低要求的来 43 | node-version: 16.14.2 # 指定 node 版本 44 | # step 3. 安装pnpm 45 | - name: Install pnpm 46 | uses: pnpm/action-setup@v2 47 | with: 48 | # 如果你指定了pnpm的最低版本要求,需要更改 49 | version: '8.10.0' 50 | # step 4. 安装依赖并打包 51 | - name: Install dependencies 52 | run: pnpm install 53 | - name: Build 54 | run: pnpm build 55 | 56 | - name: Setup Pages 57 | uses: actions/configure-pages@v3 58 | - name: Upload artifact 59 | uses: actions/upload-pages-artifact@v1 60 | with: 61 | # 打包输出的目录,建议保持不动 62 | path: './dist' 63 | - name: Deploy to GitHub Pages 64 | id: deployment 65 | uses: actions/deploy-pages@v2 #使用插件 => https://github.com/actions/deploy-pages -------------------------------------------------------------------------------- /vite.config.ts: -------------------------------------------------------------------------------- 1 | import { fileURLToPath, URL } from 'node:url' 2 | 3 | import { defineConfig, loadEnv } from 'vite' 4 | import vue from '@vitejs/plugin-vue' 5 | import vueJsx from '@vitejs/plugin-vue-jsx' 6 | import legacy from '@vitejs/plugin-legacy' 7 | import VueDevTools from 'vite-plugin-vue-devtools' 8 | import { createHtmlPlugin } from 'vite-plugin-html' 9 | import UnoCSS from 'unocss/vite' 10 | import ProgressBar from 'vite-plugin-progress' 11 | 12 | // https://vitejs.dev/config/ 13 | export default defineConfig((config) => { 14 | const CWD = process.cwd() 15 | const { mode, command } = config 16 | const { VITE_BASE_URL, VITE_TITLE, VITE_DROP_CONSOLE } = loadEnv(mode, CWD) 17 | const currentVersion = process.env['npm_package_version']! 18 | // let buildPath = `output/${mode}/${currentVersion.replaceAll('.','-')}` 19 | 20 | return { 21 | base: VITE_BASE_URL, 22 | server: { 23 | host: '0.0.0.0', 24 | port: 8000 25 | }, 26 | plugins: [ 27 | vue(), 28 | vueJsx(), 29 | legacy({ 30 | targets: ['defaults', 'not IE 11'] 31 | }), 32 | VueDevTools(), 33 | createHtmlPlugin({ 34 | minify: true, 35 | inject: { 36 | data: { 37 | title: VITE_TITLE 38 | } 39 | } 40 | }), 41 | UnoCSS(), 42 | ProgressBar() 43 | ], 44 | resolve: { 45 | alias: { 46 | '@': fileURLToPath(new URL('./src', import.meta.url)) 47 | } 48 | }, 49 | //优化 50 | optimizeDeps: { 51 | include: [] 52 | }, 53 | esbuild: { 54 | pure: VITE_DROP_CONSOLE === 'true' ? ['console.log', 'debugger'] : [] 55 | }, 56 | //构建目标 57 | build: { 58 | target: 'es2017', 59 | minify: 'esbuild', 60 | cssTarget: 'chrome79', 61 | chunkSizeWarningLimit: 2000, 62 | outDir: 'dist', 63 | //rollupOptions 64 | rollupOptions: { 65 | output: { 66 | entryFileNames: 'js/[name]-[hash].js', 67 | chunkFileNames: 'js/[name]-[hash].js', 68 | assetFileNames(chunkInfo) { 69 | if (chunkInfo.name?.endsWith('.css')) { 70 | return 'css/[name]-[hash].css' 71 | } 72 | const imagesExts = ['.png', 'jpeg', 'jpg', '.svg', '.webp'] 73 | if (imagesExts.some((ext) => chunkInfo.name?.endsWith(ext))) { 74 | return 'images/[name]-[hash][ext]' 75 | } 76 | return 'assets/[name]-[hash][ext]' 77 | } 78 | } 79 | } 80 | } 81 | } 82 | }) 83 | -------------------------------------------------------------------------------- /scripts/build.mjs: -------------------------------------------------------------------------------- 1 | import inquirer from 'inquirer' 2 | import semver from 'semver' 3 | import chalk from 'chalk' 4 | import consola from 'consola' 5 | import { execSync } from 'child_process' 6 | import path from 'path' 7 | import fs from 'fs' 8 | import { getVersion, setVersion } from './version.mjs' 9 | import { getCurrentCommitInfo, getGitUser } from './git.mjs' 10 | import { buildImage, dockerIsRunning, exitDocker } from './docker.mjs' 11 | import { writeChangelog } from './changelog.mjs' 12 | import { CMD } from './vars.mjs' 13 | function prompt(){ 14 | 15 | //get current version 16 | const currentVersion = getVersion() 17 | const username = getGitUser(); 18 | const info = getCurrentCommitInfo() 19 | 20 | const hasDocker = exitDocker() 21 | 22 | const versions ={ 23 | major: semver.inc(currentVersion,'major'), 24 | minor:semver.inc(currentVersion,'minor'), 25 | patch:semver.inc(currentVersion,'patch'), 26 | prerelease:semver.inc(currentVersion,'prerelease','beta') 27 | } 28 | 29 | /** 30 | * questions for inquirer 31 | * @type {import('inquirer').Question[]} 32 | */ 33 | const questions = [ 34 | //step1: build mode 35 | { 36 | type:"list", 37 | name:"mode", 38 | message:"请选择打包模式:", 39 | choices:[ 40 | {name:`测试打包`,value:"test"}, 41 | {name:"本地开发打包",value:"development"}, 42 | {name:"生产打包",value:"production"} 43 | ] 44 | }, 45 | //step2: ask to generate version 46 | { 47 | type:"confirm", 48 | name:'updateVersion', 49 | message:`是否更新版本号(当前版本:${currentVersion})?`, 50 | }, 51 | //step3: the mode of version 52 | { 53 | type:"list", 54 | name:"version", 55 | message:`请选择你要更新的版本号模式,当前版本号:${currentVersion}`, 56 | choices: [ 57 | {name:`大的版本迁移,新建分支,项目结构改变,或者破坏式不兼容的升级(${versions.major})`,value:versions.major}, 58 | {name:`新增功能,增加新的库包等(${versions.minor})`,value: versions.minor}, 59 | {name:`bug的修复,样式调整、文档修改等(${versions.patch})`,value: versions.patch}, 60 | {name:`预览功能打包(${versions.prerelease})`,value: versions.prerelease} 61 | ], 62 | when:(answers)=>{ 63 | return answers.updateVersion 64 | } 65 | }, 66 | //step4: ask to generate changelog 67 | { 68 | type:"confirm", 69 | name:"useLog", 70 | message:"是否生成changelog", 71 | when:(answers)=>{ 72 | return answers.updateVersion 73 | } 74 | }, 75 | //step5: input changelog info, default is latest commit message 76 | { 77 | type:"input", 78 | name:"logInfo", 79 | message:"请输入changelog说明(默认为最新提交信息)", 80 | default:info.message, 81 | when:(answers)=>{ 82 | return answers.useLog 83 | } 84 | }, 85 | //step6: ask use docker or not 86 | { 87 | type:"confirm", 88 | name:'useDocker', 89 | message:'是否打包生成docker镜像?', 90 | when:()=>hasDocker 91 | }, 92 | { 93 | type:"input", 94 | name:"imageName", 95 | message:"请输入你的镜像名:", 96 | default:'web-app', 97 | when:(answers)=>answers.useDocker 98 | } 99 | ] 100 | 101 | return inquirer.prompt(questions) 102 | } 103 | 104 | //record info 105 | function recordBuildInfo(){ 106 | 107 | } 108 | 109 | (function main(){ 110 | prompt().then((answers)=>{ 111 | const {updateVersion,mode} =answers 112 | const version = answers.version || getVersion() 113 | const outputPath = `./output/${mode}/dist(${version})` 114 | if(updateVersion){ 115 | console.info(chalk.blue(`更新应用版本:${getVersion()}`)) 116 | setVersion(answers.version) 117 | consola.success(chalk.green('版本号修改成功')) 118 | } 119 | // start build 120 | consola.info('开始打包...') 121 | //vite 122 | const buildCommand = `vite build --mode ${answers.mode}` 123 | consola.info(buildCommand) 124 | const startTime = Date.now() 125 | execSync(buildCommand,{stdio:'inherit',encoding:'utf8'}); 126 | consola.success(chalk.green('打包完成.')) 127 | const buildEndTime = Date.now() 128 | if(answers.useLog){ 129 | writeChangelog({version:answers.version,startTime:startTime,message:answers.logInfo}) 130 | } 131 | if(answers.useDocker){ 132 | if(!dockerIsRunning()){ 133 | consola.error(chalk.red('docker进程暂未启动')) 134 | } else{ 135 | consola.info(chalk.blue('docker开始打包')) 136 | const imageName = answers.imageName 137 | const outputName = `docker/${answers.mode}/${imageName}-${version}.tar` 138 | const configPath = `Dockerfile-${answers.mode}` 139 | const author = getGitUser() 140 | //create use buildx instance 141 | execSync(`docker buildx create --use`); 142 | mkdir(`docker/${mode}`) 143 | execSync(`docker build -f ${configPath} -t ${imageName}:${version} -o type=tar,dest=${outputName} .`) 144 | consola.success(chalk.green('docker 打包成功')) 145 | } 146 | } 147 | mkdir(outputPath) 148 | fs.cpSync('./dist',outputPath,{recursive:true}) 149 | fs.rmSync('./dist',{recursive:true}) 150 | consola.success(chalk.green('******本地打包完成******')) 151 | }).catch((err)=>{ 152 | console.log(err) 153 | }) 154 | })() 155 | 156 | 157 | /** 158 | * 159 | * @param {string} pathstr 160 | */ 161 | function mkdir(pathstr){ 162 | const paths = pathstr.split('/').filter(item=>!item.includes('.')); 163 | let current = CMD; 164 | while (paths.length){ 165 | current = current+'/'+paths.shift() 166 | if(!fs.existsSync(current)){ 167 | fs.mkdirSync(current) 168 | } 169 | } 170 | } 171 | 172 | --------------------------------------------------------------------------------