From f892722220b707c037afe6c05d64198f8a8a372f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=89=E5=92=B2=E6=99=BA=E5=AD=90=20Kevin=20Deng?= Date: Wed, 4 Jan 2023 21:26:30 +0800 Subject: [PATCH] refactor: env config (#769) --- components/nav/NavFooter.vue | 10 +++--- components/nav/NavTitle.vue | 7 ++-- composables/setups.ts | 12 ++++--- config/env.ts | 39 +++++++++++++++++++++ config/pwa.ts | 62 ++++++++++++++++++---------------- modules/build-info.ts | 17 ++++++---- modules/pwa/index.ts | 13 ++++--- modules/pwa/types.ts | 7 ++-- nuxt.config.ts | 4 +-- pages/settings/about/index.vue | 8 ++--- server/shared.ts | 2 +- shims.d.ts | 3 +- types/index.ts | 1 + 13 files changed, 121 insertions(+), 64 deletions(-) create mode 100644 config/env.ts diff --git a/components/nav/NavFooter.vue b/components/nav/NavFooter.vue index e91f2f6b..81ae1394 100644 --- a/components/nav/NavFooter.vue +++ b/components/nav/NavFooter.vue @@ -1,5 +1,5 @@ diff --git a/composables/setups.ts b/composables/setups.ts index 1adbd554..59519379 100644 --- a/composables/setups.ts +++ b/composables/setups.ts @@ -1,13 +1,11 @@ import { pwaInfo } from 'virtual:pwa-info' import type { Link } from '@unhead/schema' import type { Directions } from 'vue-i18n-routing' +import { buildInfo } from 'virtual:build-info' import { APP_NAME } from '~/constants' import type { LocaleObject } from '#i18n' export function setupPageHeader() { - const isDev = process.dev - const isPreview = useRuntimeConfig().public.env === 'staging' - const i18n = useI18n() const link: Link[] = [] @@ -42,7 +40,13 @@ export function setupPageHeader() { lang: () => i18n.locale.value, dir: () => localeMap[i18n.locale.value] ?? 'auto', }, - titleTemplate: title => `${title ? `${title} | ` : ''}${APP_NAME}${isDev ? ' (dev)' : isPreview ? ' (preview)' : ''}`, + titleTemplate: (title) => { + let titleTemplate = title ? `${title} | ` : '' + titleTemplate += APP_NAME + if (buildInfo.env !== 'release') + titleTemplate += ` (${buildInfo.env})` + return titleTemplate + }, link, }) } diff --git a/config/env.ts b/config/env.ts new file mode 100644 index 00000000..4aadecb8 --- /dev/null +++ b/config/env.ts @@ -0,0 +1,39 @@ +import Git from 'simple-git' +import { isDevelopment } from 'std-env' + +export { version } from '../package.json' + +/** + * Environment variable `PULL_REQUEST` provided by Netlify. + * @see {@link https://docs.netlify.com/configure-builds/environment-variables/#git-metadata} + * + * Whether triggered by a GitHub PR + */ +export const isPR = process.env.PULL_REQUEST === 'true' + +/** + * Environment variable `CONTEXT` provided by Netlify. + * @see {@link https://docs.netlify.com/configure-builds/environment-variables/#build-metadata} + * + * Whether triggered by PR, `deploy-preview` or `dev`. + */ +export const isPreview = isPR || process.env.CONTEXT === 'deploy-preview' || process.env.CONTEXT === 'dev' + +const git = Git() +export const getGitInfo = async () => { + const branch = await git.revparse(['--abbrev-ref', 'HEAD']) + const commit = await git.revparse(['HEAD']) + return { branch, commit } +} + +export const getEnv = async () => { + const { commit, branch } = await getGitInfo() + const env = isDevelopment + ? 'dev' + : isPreview + ? 'preview' + : branch === 'main' + ? 'main' + : 'release' + return { commit, branch, env } as const +} diff --git a/config/pwa.ts b/config/pwa.ts index f47a2846..4838ded0 100644 --- a/config/pwa.ts +++ b/config/pwa.ts @@ -1,7 +1,7 @@ import { isCI, isDevelopment } from 'std-env' import type { VitePWANuxtOptions } from '../modules/pwa/types' - -const isPreview = process.env.PULL_REQUEST === 'true' +import { APP_NAME } from '../constants' +import { getEnv } from './env' export const pwa: VitePWANuxtOptions = { mode: isCI ? 'production' : 'development', @@ -13,33 +13,37 @@ export const pwa: VitePWANuxtOptions = { strategies: 'injectManifest', injectRegister: false, includeManifestIcons: false, - manifest: { - scope: '/', - id: '/', - name: `Elk${isCI ? isPreview ? ' (preview)' : '' : ' (dev)'}`, - short_name: `Elk${isCI ? isPreview ? ' (preview)' : '' : ' (dev)'}`, - description: `A nimble Mastodon Web Client${isCI ? isPreview ? ' (preview)' : '' : ' (development)'}`, - theme_color: '#ffffff', - icons: [ - { - src: 'pwa-192x192.png', - sizes: '192x192', - type: 'image/png', - }, - { - src: 'pwa-512x512.png', - sizes: '512x512', - type: 'image/png', - }, - /* - { - src: 'logo.svg', - sizes: '250x250', - type: 'image/png', - purpose: 'any maskable', - }, -*/ - ], + manifest: async () => { + const { env } = await getEnv() + const envName = `${env !== 'release' ? '' : ` (${env})`}` + return { + scope: '/', + id: '/', + name: `${APP_NAME}${envName}`, + short_name: `${APP_NAME}${envName}`, + description: `A nimble Mastodon Web Client${envName}`, + theme_color: '#ffffff', + icons: [ + { + src: 'pwa-192x192.png', + sizes: '192x192', + type: 'image/png', + }, + { + src: 'pwa-512x512.png', + sizes: '512x512', + type: 'image/png', + }, + /* + { + src: 'logo.svg', + sizes: '250x250', + type: 'image/png', + purpose: 'any maskable', + }, + */ + ], + } }, injectManifest: { globPatterns: ['**/*.{js,json,css,html,txt,svg,png,ico,webp,woff,woff2,ttf,eot,otf,wasm}'], diff --git a/modules/build-info.ts b/modules/build-info.ts index 7da46d4e..ac93d96c 100644 --- a/modules/build-info.ts +++ b/modules/build-info.ts @@ -1,20 +1,23 @@ import { addVitePlugin, defineNuxtModule } from '@nuxt/kit' -import Git from 'simple-git' -import { version } from '../package.json' +import { getEnv, version } from '../config/env' import type { BuildInfo } from '~/types' export default defineNuxtModule({ meta: { name: 'elk:build-info', }, - async setup() { - const git = Git() + async setup(_options, nuxt) { + const { env, commit, branch } = await getEnv() + nuxt.options.runtimeConfig.public.env = env + const buildInfo: BuildInfo = { version, time: +Date.now(), - commit: await git.revparse(['HEAD']), - branch: await git.revparse(['--abbrev-ref', 'HEAD']), + commit, + branch, + env, } + addVitePlugin({ name: 'elk:build-info', resolveId(id) { @@ -23,7 +26,7 @@ export default defineNuxtModule({ }, load(id) { if (id === 'virtual:build-info') - return `export default ${JSON.stringify(buildInfo, null, 2)}` + return `export const buildInfo = ${JSON.stringify(buildInfo, null, 2)}` }, }) }, diff --git a/modules/pwa/index.ts b/modules/pwa/index.ts index 40d34357..fbf369fc 100644 --- a/modules/pwa/index.ts +++ b/modules/pwa/index.ts @@ -1,5 +1,5 @@ import { defineNuxtModule } from '@nuxt/kit' -import type { VitePluginPWAAPI } from 'vite-plugin-pwa' +import type { VitePWAOptions, VitePluginPWAAPI } from 'vite-plugin-pwa' import { VitePWA } from 'vite-plugin-pwa' import type { Plugin } from 'vite' import type { VitePWANuxtOptions } from './types' @@ -32,14 +32,17 @@ export default defineNuxtModule({ if (plugin) throw new Error('Remove vite-plugin-pwa plugin from Vite Plugins entry in Nuxt config file!') }) - nuxt.hook('vite:extendConfig', (viteInlineConfig, { isClient }) => { + nuxt.hook('vite:extendConfig', async (viteInlineConfig, { isClient }) => { viteInlineConfig.plugins = viteInlineConfig.plugins || [] const plugin = viteInlineConfig.plugins.find(p => p && typeof p === 'object' && 'name' in p && p.name === 'vite-plugin-pwa') if (plugin) throw new Error('Remove vite-plugin-pwa plugin from Vite Plugins entry in Nuxt config file!') - - configurePWAOptions(options, nuxt) - const plugins = VitePWA(options) + const resolvedOptions: Partial = { + ...options, + manifest: options.manifest ? await options.manifest() : undefined, + } + configurePWAOptions(resolvedOptions, nuxt) + const plugins = VitePWA(resolvedOptions) viteInlineConfig.plugins.push(plugins) if (isClient) vitePwaClientPlugin = plugins.find(p => p.name === 'vite-plugin-pwa') as Plugin diff --git a/modules/pwa/types.ts b/modules/pwa/types.ts index 90446c52..7d3af0d5 100644 --- a/modules/pwa/types.ts +++ b/modules/pwa/types.ts @@ -1,6 +1,9 @@ -import type { VitePWAOptions } from 'vite-plugin-pwa' +import type { ManifestOptions, VitePWAOptions } from 'vite-plugin-pwa' +import type { Overwrite } from '../../types/utils' -export interface VitePWANuxtOptions extends Partial {} +export type VitePWANuxtOptions = Overwrite, { + manifest?: () => Promise> +}> declare module '@nuxt/schema' { interface NuxtConfig { diff --git a/nuxt.config.ts b/nuxt.config.ts index 2100c596..c46c7bca 100644 --- a/nuxt.config.ts +++ b/nuxt.config.ts @@ -3,9 +3,9 @@ import Inspect from 'vite-plugin-inspect' import { isCI, isDevelopment } from 'std-env' import { i18n } from './config/i18n' import { pwa } from './config/pwa' +import { isPreview } from './config/env' const { resolve } = createResolver(import.meta.url) -const isPreview = process.env.PULL_REQUEST === 'true' || process.env.CONTEXT === 'deploy-preview' || process.env.CONTEXT === 'dev' export default defineNuxtConfig({ typescript: { @@ -90,7 +90,7 @@ export default defineNuxtConfig({ inviteToken: '', }, public: { - env: isCI ? isPreview ? 'staging' : 'production' : 'local', + env: '', // set in build-info module pwaEnabled: !isDevelopment || process.env.VITE_DEV_PWA === 'true', translateApi: '', }, diff --git a/pages/settings/about/index.vue b/pages/settings/about/index.vue index 6993f277..c51a5838 100644 --- a/pages/settings/about/index.vue +++ b/pages/settings/about/index.vue @@ -1,7 +1,7 @@