29 changed files with 562 additions and 117 deletions
@ -0,0 +1,21 @@ |
|||||
|
const css = ['//cdn.bootcdn.net/ajax/libs/nprogress/0.2.0/nprogress.min.css']; |
||||
|
|
||||
|
// TODO use esm?
|
||||
|
const js = [ |
||||
|
'//cdn.bootcdn.net/ajax/libs/vue/3.0.0/vue.global.prod.js', |
||||
|
'//cdn.bootcdn.net/ajax/libs/vue-router/4.0.0-beta.13/vue-router.global.min.js', |
||||
|
'//cdn.bootcdn.net/ajax/libs/vuex/4.0.0-beta.4/vuex.global.prod.js', |
||||
|
'//cdn.bootcdn.net/ajax/libs/axios/0.19.2/axios.min.js', |
||||
|
'//cdn.bootcdn.net/ajax/libs/qs/6.9.4/qs.min.js', |
||||
|
'//cdn.bootcdn.net/ajax/libs/nprogress/0.2.0/nprogress.min.js', |
||||
|
// '//cdn.bootcdn.net/ajax/libs/lodash.js/4.17.15/lodash.min.js',
|
||||
|
// '//cdn.bootcdn.net/ajax/libs/crypto-js/3.3.0/crypto-js.min.js',
|
||||
|
// '//cdn.bootcdn.net/ajax/libs/vue-i18n/8.18.1/vue-i18n.min.js',
|
||||
|
]; |
||||
|
|
||||
|
export const externals = ['vue', 'vuex', 'vue-router', 'axios', 'qs', 'nprogress']; |
||||
|
|
||||
|
export const cdnConf = { |
||||
|
css, |
||||
|
js, |
||||
|
}; |
||||
@ -1,10 +0,0 @@ |
|||||
import moment from 'moment'; |
|
||||
// @ts-ignore
|
|
||||
import pkg from '../../../package.json'; |
|
||||
export function setupBasicEnv() { |
|
||||
// version
|
|
||||
process.env.VITE_VERSION = (pkg as any).version; |
|
||||
// build time
|
|
||||
process.env.VITE_APP_BUILD_TIME = moment().format('YYYY-MM-DD HH:mm:ss'); |
|
||||
process.env.VITE_BUILD_SHORT_TIME = moment().format('MMDDHHmmss'); |
|
||||
} |
|
||||
@ -0,0 +1 @@ |
|||||
|
export const GLOB_CONFIG_FILE_NAME = '_app.config.js'; |
||||
@ -0,0 +1,5 @@ |
|||||
|
export const getShortName = (env: any) => { |
||||
|
return `__PRODUCTION__${env.VITE_GLOB_APP_SHORT_NAME || '__APP'}__CONF__` |
||||
|
.toUpperCase() |
||||
|
.replace(/\s/g, ''); |
||||
|
}; |
||||
@ -0,0 +1,36 @@ |
|||||
|
// js调用cli 兼容调用ts
|
||||
|
|
||||
|
const { sh } = require('tasksfile'); |
||||
|
const { argv } = require('yargs'); |
||||
|
|
||||
|
let command = ``; |
||||
|
|
||||
|
Object.keys(argv).forEach((key) => { |
||||
|
if (!/^\$/.test(key) && key !== '_') { |
||||
|
// @ts-ignore
|
||||
|
if (argv[key]) { |
||||
|
command += `--${key} `; |
||||
|
} |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
// 执行任务名称
|
||||
|
let taskList = argv._; |
||||
|
|
||||
|
let NODE_ENV = process.env.NODE_ENV || 'development'; |
||||
|
|
||||
|
if (taskList.includes('build') || taskList.includes('report') || taskList.includes('preview')) { |
||||
|
NODE_ENV = 'production'; |
||||
|
} |
||||
|
|
||||
|
if (taskList && Array.isArray(taskList) && taskList.length) { |
||||
|
sh( |
||||
|
`cross-env NODE_ENV=${NODE_ENV} ts-node --project ./build/tsconfig.json ./build/script/cli.ts ${taskList.join( |
||||
|
' ' |
||||
|
)} ${command}`,
|
||||
|
{ |
||||
|
async: true, |
||||
|
nopipe: true, |
||||
|
} |
||||
|
); |
||||
|
} |
||||
@ -0,0 +1,28 @@ |
|||||
|
// #!/usr/bin/env node
|
||||
|
|
||||
|
import { sh } from 'tasksfile'; |
||||
|
import { argv } from 'yargs'; |
||||
|
import { runBuildConfig } from './buildConf'; |
||||
|
import { runUpdateHtml } from './updateHtml'; |
||||
|
import { errorConsole, successConsole } from '../utils'; |
||||
|
|
||||
|
export const runBuild = async () => { |
||||
|
try { |
||||
|
const argvList = argv._; |
||||
|
let cmd = `cross-env NODE_ENV=production vite build`; |
||||
|
await sh(cmd, { |
||||
|
async: true, |
||||
|
nopipe: true, |
||||
|
}); |
||||
|
|
||||
|
// Generate configuration file
|
||||
|
if (!argvList.includes('no-conf')) { |
||||
|
await runBuildConfig(); |
||||
|
} |
||||
|
await runUpdateHtml(); |
||||
|
successConsole('Vite Build successfully!'); |
||||
|
} catch (error) { |
||||
|
errorConsole('Vite Build Error\n' + error); |
||||
|
process.exit(1); |
||||
|
} |
||||
|
}; |
||||
@ -0,0 +1,44 @@ |
|||||
|
import { GLOB_CONFIG_FILE_NAME } from '../constant'; |
||||
|
import fs, { writeFileSync } from 'fs-extra'; |
||||
|
|
||||
|
import viteConfig from '../../vite.config'; |
||||
|
import { errorConsole, successConsole, getCwdPath, getEnvConfig } from '../utils'; |
||||
|
|
||||
|
const getShortName = (env: any) => { |
||||
|
return `__PRODUCTION__${env.VITE_GLOB_APP_SHORT_NAME || '__APP'}__CONF__` |
||||
|
.toUpperCase() |
||||
|
.replace(/\s/g, ''); |
||||
|
}; |
||||
|
|
||||
|
function createConfig( |
||||
|
{ |
||||
|
configName, |
||||
|
config, |
||||
|
configFileName = GLOB_CONFIG_FILE_NAME, |
||||
|
}: { configName: string; config: any; configFileName?: string } = { configName: '', config: {} } |
||||
|
) { |
||||
|
try { |
||||
|
const windowConf = `window.${configName}`; |
||||
|
const outDir = viteConfig.outDir || 'dist'; |
||||
|
const configStr = `${windowConf}=${JSON.stringify(config)};
|
||||
|
|
||||
|
Object.freeze(${windowConf}); |
||||
|
Object.defineProperty(window, "${configName}", { |
||||
|
configurable: false, |
||||
|
writable: false, |
||||
|
}); |
||||
|
`;
|
||||
|
fs.mkdirp(getCwdPath(outDir)); |
||||
|
writeFileSync(getCwdPath(`${outDir}/${configFileName}`), configStr); |
||||
|
|
||||
|
successConsole('The configuration file is build successfully!'); |
||||
|
} catch (error) { |
||||
|
errorConsole('Configuration file configuration file failed to package\n' + error); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
export function runBuildConfig() { |
||||
|
const config = getEnvConfig(); |
||||
|
const configFileName = getShortName(config); |
||||
|
createConfig({ config, configName: configFileName }); |
||||
|
} |
||||
@ -0,0 +1,45 @@ |
|||||
|
#!/usr/bin/env node |
||||
|
|
||||
|
import chalk from 'chalk'; |
||||
|
import { argv } from 'yargs'; |
||||
|
|
||||
|
import { runChangeLog } from './changelog'; |
||||
|
import { runPostInstall } from './postinstall'; |
||||
|
import { runPreview } from './preview'; |
||||
|
import { runPreserve } from './preserve'; |
||||
|
import { runBuild } from './build'; |
||||
|
|
||||
|
const task = (argv._ || [])[0]; |
||||
|
|
||||
|
console.log('Run Task: ' + chalk.cyan(task)); |
||||
|
|
||||
|
switch (task) { |
||||
|
// change log
|
||||
|
case 'log': |
||||
|
runChangeLog(); |
||||
|
break; |
||||
|
|
||||
|
case 'build': |
||||
|
runBuild(); |
||||
|
break; |
||||
|
|
||||
|
case 'preserve': |
||||
|
runPreserve(); |
||||
|
break; |
||||
|
|
||||
|
case 'postinstall': |
||||
|
runPostInstall(); |
||||
|
break; |
||||
|
|
||||
|
case 'preview': |
||||
|
runPreview(); |
||||
|
break; |
||||
|
|
||||
|
// TODO
|
||||
|
case 'gzip': |
||||
|
break; |
||||
|
default: |
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
export default {}; |
||||
@ -0,0 +1,12 @@ |
|||||
|
// 百度统计代码 用于站点部署
|
||||
|
// 只在build:site开启
|
||||
|
export const hmScript = `<script>
|
||||
|
var _hmt = _hmt || []; |
||||
|
(function() { |
||||
|
var hm = document.createElement("script"); |
||||
|
hm.src = "https://hm.baidu.com/hm.js?384d6046e02f6ac4ea075357bd0e9b43"; |
||||
|
var s = document.getElementsByTagName("script")[0]; |
||||
|
s.parentNode.insertBefore(hm, s); |
||||
|
})(); |
||||
|
</script> |
||||
|
`;
|
||||
@ -0,0 +1,98 @@ |
|||||
|
import { readFileSync, writeFileSync, existsSync } from 'fs-extra'; |
||||
|
import viteConfig, { htmlConfig } from '../../vite.config'; |
||||
|
import { getCwdPath, successConsole, errorConsole } from '../utils'; |
||||
|
import { GLOB_CONFIG_FILE_NAME } from '../constant'; |
||||
|
import { hmScript } from './hm'; |
||||
|
const pkg = require('../../package.json'); |
||||
|
|
||||
|
const { title, addHm, cdnConf, useCdn } = htmlConfig; |
||||
|
|
||||
|
function injectTitle(html: string, htmlTitle: string) { |
||||
|
if (/<\/title>/.test(html)) { |
||||
|
return html.replace(/<\/title>/, `${htmlTitle}</title>`); |
||||
|
} |
||||
|
return html; |
||||
|
} |
||||
|
|
||||
|
function injectConfigScript(html: string) { |
||||
|
const tag = `\t\t<script src='${viteConfig.base || './'}${GLOB_CONFIG_FILE_NAME}?v=${ |
||||
|
pkg.version |
||||
|
}-${new Date().getTime()}'></script>`;
|
||||
|
|
||||
|
if (/<\/head>/.test(html)) { |
||||
|
return html.replace(/<\/head>/, `${tag}\n\t\t</head>`); |
||||
|
} |
||||
|
return html; |
||||
|
} |
||||
|
|
||||
|
function injectHmScript(html: string) { |
||||
|
if (/<head>/.test(html)) { |
||||
|
return html.replace(/<head>/, `<head>\n${hmScript}`); |
||||
|
} |
||||
|
return html; |
||||
|
} |
||||
|
|
||||
|
function injectCdnCss(html: string) { |
||||
|
if (!cdnConf) return html; |
||||
|
const { css } = cdnConf; |
||||
|
if (!css || css.length === 0) return html; |
||||
|
|
||||
|
let cdnCssTag = ''; |
||||
|
for (const cssLink of css) { |
||||
|
cdnCssTag += `<link rel="stylesheet" href="${cssLink}">`; |
||||
|
} |
||||
|
if (/<\/head>/.test(html)) { |
||||
|
return html.replace(/<\/head>/, `${cdnCssTag}\n\t\t</head>`); |
||||
|
} |
||||
|
return html; |
||||
|
} |
||||
|
|
||||
|
function injectCdnjs(html: string) { |
||||
|
if (!cdnConf) return html; |
||||
|
const { js } = cdnConf; |
||||
|
if (!js || js.length === 0) return html; |
||||
|
|
||||
|
let cdnJsTag = ''; |
||||
|
for (const src of js) { |
||||
|
// TODO
|
||||
|
// <script type="importmap">
|
||||
|
// { "imports": {
|
||||
|
// "vue": "https://cdnjs.cloudflare.com/ajax/libs/vue/3.0.0/vue.esm-browser.js",
|
||||
|
// "vue-router": "https://cdnjs.cloudflare.com/ajax/libs/vue-router/4.0.0-alpha.13/vue-router.esm.js",
|
||||
|
// "vuex": "https://cdnjs.cloudflare.com/ajax/libs/vuex/4.0.0-beta.2/vuex.esm-browser.js"
|
||||
|
// } }
|
||||
|
// </script>
|
||||
|
cdnJsTag += `\t<script type="text/javascript" src="${src}"></script>\n`; |
||||
|
} |
||||
|
if (/<\/body>/.test(html)) { |
||||
|
return html.replace(/<\/body>/, `${cdnJsTag}\n</body>`); |
||||
|
} |
||||
|
return html; |
||||
|
} |
||||
|
|
||||
|
export async function runUpdateHtml() { |
||||
|
const outDir = viteConfig.outDir || 'dist'; |
||||
|
const indexPath = getCwdPath(outDir, 'index.html'); |
||||
|
if (!existsSync(`${indexPath}`)) { |
||||
|
return; |
||||
|
} |
||||
|
try { |
||||
|
let processedHtml = ''; |
||||
|
const rawHtml = readFileSync(indexPath, 'utf-8'); |
||||
|
processedHtml = rawHtml; |
||||
|
processedHtml = injectTitle(processedHtml, title); |
||||
|
processedHtml = injectConfigScript(processedHtml); |
||||
|
if (addHm) { |
||||
|
processedHtml = injectHmScript(processedHtml); |
||||
|
} |
||||
|
if (useCdn) { |
||||
|
processedHtml = injectCdnCss(processedHtml); |
||||
|
processedHtml = injectCdnjs(processedHtml); |
||||
|
} |
||||
|
|
||||
|
writeFileSync(indexPath, processedHtml); |
||||
|
successConsole('Update Html Successfully!'); |
||||
|
} catch (error) { |
||||
|
errorConsole('Update Html Error\n' + error); |
||||
|
} |
||||
|
} |
||||
@ -1,6 +0,0 @@ |
|||||
import type { GlobEnvConfig } from './src/types/config'; |
|
||||
|
|
||||
export const getGlobEnvConfig = (): GlobEnvConfig => { |
|
||||
const env = import.meta.env; |
|
||||
return (env as unknown) as GlobEnvConfig; |
|
||||
}; |
|
||||
@ -1,12 +1,13 @@ |
|||||
import { isDevMode, getEnv } from '/@/utils/env'; |
import { isDevMode, getEnv } from '/@/utils/env'; |
||||
import { useSetting } from '/@/hooks/core/useSetting'; |
import { useSetting } from '/@/hooks/core/useSetting'; |
||||
|
import moment from 'moment'; |
||||
import pkg from '../../../package.json'; |
import pkg from '../../../package.json'; |
||||
const { globSetting } = useSetting(); |
const { globSetting } = useSetting(); |
||||
|
|
||||
// Generate cache key according to version
|
// Generate cache key according to version
|
||||
export const getStorageShortName = () => { |
export const getStorageShortName = () => { |
||||
|
const shortTime = moment().format('MMDDHHmmss'); |
||||
return `${globSetting.shortName}__${getEnv()}${ |
return `${globSetting.shortName}__${getEnv()}${ |
||||
isDevMode() ? `__${(pkg as any).version}` : '__' + process.env.VITE_BUILD_SHORT_TIME |
`__${pkg.version}` + (isDevMode() ? '' : `__${shortTime}`) |
||||
}__`.toUpperCase();
|
}__`.toUpperCase();
|
||||
}; |
}; |
||||
|
|||||
Loading…
Reference in new issue