wip: support vite

This commit is contained in:
vben
2021-01-09 23:28:52 +08:00
parent 1d3007f030
commit 99ac309fa9
105 changed files with 954 additions and 2170 deletions

View File

@@ -1,26 +0,0 @@
// #!/usr/bin/env node
import { sh } from 'tasksfile';
import { errorConsole, successConsole } from '../utils';
export const runChangeLog = async () => {
try {
let cmd = `conventional-changelog -p custom-config -i CHANGELOG.md -s -r 0 `;
await sh(cmd, {
async: true,
nopipe: true,
});
await sh('prettier --write **/CHANGELOG.md ', {
async: true,
nopipe: true,
});
successConsole('CHANGE_LOG.md generated successfully');
} catch (error) {
errorConsole('CHANGE_LOG.md generated error\n' + error);
process.exit(1);
}
};
runChangeLog();

View File

@@ -3,7 +3,6 @@
import { argv } from 'yargs';
import { runBuildConfig } from './buildConf';
import { errorConsole, successConsole } from '../utils';
import { startGzipStyle } from '../vite/plugin/gzip/compress';
export const runBuild = async () => {
try {
@@ -13,8 +12,6 @@ export const runBuild = async () => {
if (!argvList.includes('no-conf')) {
await runBuildConfig();
}
// await runUpdateHtml();
await startGzipStyle();
successConsole('Vite Build successfully!');
} catch (error) {
errorConsole('Vite Build Error\n' + error);

View File

@@ -63,11 +63,11 @@ export function getIPAddress() {
return '';
}
export function isDevFn(mode: 'development' | 'production'): boolean {
export function isDevFn(mode: string): boolean {
return mode === 'development';
}
export function isProdFn(mode: 'development' | 'production'): boolean {
export function isProdFn(mode: string): boolean {
return mode === 'production';
}
@@ -85,13 +85,6 @@ export function isBuildGzip(): boolean {
return process.env.VITE_BUILD_GZIP === 'true';
}
/**
* Whether to generate package site
*/
export function isSiteMode(): boolean {
return process.env.SITE === 'true';
}
export interface ViteEnv {
VITE_PORT: number;
VITE_USE_MOCK: boolean;
@@ -99,10 +92,12 @@ export interface ViteEnv {
VITE_PUBLIC_PATH: string;
VITE_PROXY: [string, string][];
VITE_GLOB_APP_TITLE: string;
VITE_GLOB_APP_SHORT_NAME: string;
VITE_USE_CDN: boolean;
VITE_DROP_CONSOLE: boolean;
VITE_BUILD_GZIP: boolean;
VITE_DYNAMIC_IMPORT: boolean;
VITE_LEGACY: boolean;
}
// Read all environment variable configuration files to process.env

View File

@@ -1,12 +0,0 @@
// Baidu statistics code for site deployment
// Only open in 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>
`;

12
build/vite/plugin/gzip.ts Normal file
View File

@@ -0,0 +1,12 @@
import gzipPlugin from 'rollup-plugin-gzip';
import { isBuildGzip } from '../../utils';
import { Plugin } from 'vite';
export function configGzipPlugin(isBuild: boolean): Plugin | Plugin[] {
const useGzip = isBuild && isBuildGzip;
if (useGzip) {
return gzipPlugin();
}
return [];
}

View File

@@ -1,35 +0,0 @@
import { gzip } from 'zlib';
import { readFileSync, writeFileSync } from 'fs';
import { GzipPluginOptions } from './types';
import { readAllFile, getCwdPath, isBuildGzip, isSiteMode } from '../../../utils';
export function startGzip(
fileContent: string | Buffer,
options: GzipPluginOptions = {}
): Promise<Buffer> {
return new Promise((resolve, reject) => {
gzip(fileContent, options.gzipOptions || {}, (err, result) => {
if (err) {
reject(err);
} else {
resolve(result);
}
});
});
}
// 手动压缩css
export async function startGzipStyle() {
if (isBuildGzip() || isSiteMode()) {
const outDir = 'dist';
const assets = '_assets';
const allCssFile = readAllFile(getCwdPath(outDir, assets), /\.(css)$/);
for (const path of allCssFile) {
const source = readFileSync(path);
const content = await startGzip(source);
const ds = path.split('/');
const fileName = ds[ds.length - 1];
writeFileSync(getCwdPath(outDir, assets, `${fileName}.gz`), content);
}
}
}

View File

@@ -1,196 +0,0 @@
// 修改自https://github.com/kryops/rollup-plugin-gzip
// 因为rollup-plugin-gzip不支持vite
// vite对css打包独立的。所以不能在打包的时候顺带打包css
// TODO rc.9会支持 configurBuild 配置项。到时候重新修改
import { readFile, writeFile } from 'fs';
import { basename } from 'path';
import { promisify } from 'util';
import { gzip } from 'zlib';
import { OutputAsset, OutputChunk, OutputOptions, Plugin } from 'rollup';
import { GzipPluginOptions } from './types';
const isFunction = (arg: unknown): arg is (...args: any[]) => any => typeof arg === 'function';
const isRegExp = (arg: unknown): arg is RegExp =>
Object.prototype.toString.call(arg) === '[object RegExp]';
export type StringMappingOption = (originalString: string) => string;
export type CustomCompressionOption = (
content: string | Buffer
) => string | Buffer | Promise<string | Buffer>;
const readFilePromise = promisify(readFile);
const writeFilePromise = promisify(writeFile);
// functionality partially copied from rollup
/**
* copied from https://github.com/rollup/rollup/blob/master/src/rollup/index.ts#L450
*/
function isOutputChunk(file: OutputAsset | OutputChunk): file is OutputChunk {
return typeof (file as OutputChunk).code === 'string';
}
/**
* Gets the string/buffer content from a file object.
* Important for adding source map comments
*
* Copied partially from rollup.writeOutputFile
* https://github.com/rollup/rollup/blob/master/src/rollup/index.ts#L454
*/
function getOutputFileContent(
outputFileName: string,
outputFile: OutputAsset | OutputChunk,
outputOptions: OutputOptions
): string | Buffer {
if (isOutputChunk(outputFile)) {
let source: string | Buffer;
source = outputFile.code;
if (outputOptions.sourcemap && outputFile.map) {
const url =
outputOptions.sourcemap === 'inline'
? outputFile.map.toUrl()
: `${basename(outputFileName)}.map`;
// https://github.com/rollup/rollup/blob/master/src/utils/sourceMappingURL.ts#L1
source += `//# source` + `MappingURL=${url}\n`;
}
return source;
} else {
return typeof outputFile.source === 'string'
? outputFile.source
: // just to be sure, as it is typed string | Uint8Array in rollup 2.0.0
Buffer.from(outputFile.source);
}
}
// actual plugin code
function gzipPlugin(options: GzipPluginOptions = {}): Plugin {
// check for old options
if ('algorithm' in options) {
console.warn(
'[rollup-plugin-gzip] The "algorithm" option is not supported any more! ' +
'Use "customCompression" instead to specify a different compression algorithm.'
);
}
if ('options' in options) {
console.warn('[rollup-plugin-gzip] The "options" option was renamed to "gzipOptions"!');
}
if ('additional' in options) {
console.warn('[rollup-plugin-gzip] The "additional" option was renamed to "additionalFiles"!');
}
if ('delay' in options) {
console.warn('[rollup-plugin-gzip] The "delay" option was renamed to "additionalFilesDelay"!');
}
const compressGzip: CustomCompressionOption = (fileContent) => {
return new Promise((resolve, reject) => {
gzip(fileContent, options.gzipOptions || {}, (err, result) => {
if (err) {
reject(err);
} else {
resolve(result);
}
});
});
};
const doCompress = options.customCompression || compressGzip;
const mapFileName: StringMappingOption = isFunction(options.fileName)
? (options.fileName as StringMappingOption)
: (fileName: string) => fileName + (options.fileName || '.gz');
const plugin: Plugin = {
name: 'gzip',
generateBundle(outputOptions, bundle) {
return Promise.all(
Object.keys(bundle)
.map((fileName) => {
const fileEntry = bundle[fileName];
// file name filter option check
const fileNameFilter = options.filter || /\.(js|mjs|json|css|html)$/;
if (isRegExp(fileNameFilter) && !fileName.match(fileNameFilter)) {
return Promise.resolve();
}
if (
isFunction(fileNameFilter) &&
!(fileNameFilter as (x: string) => boolean)(fileName)
) {
return Promise.resolve();
}
const fileContent = getOutputFileContent(fileName, fileEntry, outputOptions);
// minSize option check
if (options.minSize && options.minSize > fileContent.length) {
return Promise.resolve();
}
return Promise.resolve(doCompress(fileContent))
.then((compressedContent) => {
const compressedFileName = mapFileName(fileName);
bundle[compressedFileName] = {
type: 'asset', // Rollup >= 1.21
name: compressedFileName,
fileName: compressedFileName,
isAsset: true, // Rollup < 1.21
source: compressedContent,
};
})
.catch((err: any) => {
console.error(err);
return Promise.reject('[rollup-plugin-gzip] Error compressing file ' + fileName);
});
})
.concat([
(() => {
if (!options.additionalFiles || !options.additionalFiles.length)
return Promise.resolve();
const compressAdditionalFiles = () =>
Promise.all(
options.additionalFiles!.map((filePath) =>
readFilePromise(filePath)
.then((fileContent) => doCompress(fileContent))
.then((compressedContent) => {
return writeFilePromise(mapFileName(filePath), compressedContent);
})
.catch(() => {
return Promise.reject(
'[rollup-plugin-gzip] Error compressing additional file ' +
filePath +
'. Please check the spelling of your configured additionalFiles. ' +
'You might also have to increase the value of the additionalFilesDelay option.'
);
})
)
) as Promise<any>;
// additional files can be processed outside of rollup after a delay
// for older plugins or plugins that write to disk (curcumventing rollup) without awaiting
const additionalFilesDelay = options.additionalFilesDelay || 0;
if (additionalFilesDelay) {
setTimeout(compressAdditionalFiles, additionalFilesDelay);
return Promise.resolve();
} else {
return compressAdditionalFiles();
}
})(),
])
) as Promise<any>;
},
};
return plugin;
}
export default gzipPlugin;

View File

@@ -1,56 +0,0 @@
import type { ZlibOptions } from 'zlib';
export type StringMappingOption = (originalString: string) => string;
export type CustomCompressionOption = (
content: string | Buffer
) => string | Buffer | Promise<string | Buffer>;
export interface GzipPluginOptions {
/**
* Control which of the output files to compress
*
* Defaults to `/\.(js|mjs|json|css|html)$/`
*/
filter?: RegExp | ((fileName: string) => boolean);
/**
* GZIP compression options, see https://nodejs.org/api/zlib.html#zlib_class_options
*/
gzipOptions?: ZlibOptions;
/**
* Specified the minimum size in Bytes for a file to get compressed.
* Files that are smaller than this threshold will not be compressed.
* This does not apply to the files specified through `additionalFiles`!
*/
minSize?: number;
/**
* This option allows you to compress additional files outside of the main rollup bundling process.
* The processing is delayed to make sure the files are written on disk; the delay is controlled
* through `additionalFilesDelay`.
*/
additionalFiles?: string[];
/**
* This options sets a delay (ms) before the plugin compresses the files specified through `additionalFiles`.
* Increase this value if your artifacts take a long time to generate.
*
* Defaults to `2000`
*/
additionalFilesDelay?: number;
/**
* Set a custom compression algorithm. The function can either return the compressed contents synchronously,
* or otherwise return a promise for asynchronous processing.
*/
customCompression?: CustomCompressionOption;
/**
* Set a custom file name convention for the compressed files. Can be a suffix string or a function
* returning the file name.
*
* Defaults to `.gz`
*/
fileName?: string | StringMappingOption;
}

View File

@@ -1,37 +1,32 @@
import type { Plugin } from 'vite';
import ViteHtmlPlugin from 'vite-plugin-html';
import { isProdFn, isSiteMode, ViteEnv } from '../../utils';
import html from 'vite-plugin-html';
import { ViteEnv } from '../../utils';
import { hmScript } from '../hm';
// @ts-ignore
import pkg from '../../../package.json';
import { GLOB_CONFIG_FILE_NAME } from '../../constant';
export function setupHtmlPlugin(
plugins: Plugin[],
env: ViteEnv,
mode: 'development' | 'production'
) {
export function configHtmlPlugin(env: ViteEnv, isBuild: boolean) {
const { VITE_GLOB_APP_TITLE, VITE_PUBLIC_PATH } = env;
const htmlPlugin = ViteHtmlPlugin({
// html title
title: VITE_GLOB_APP_TITLE,
minify: isProdFn(mode),
options: {
publicPath: VITE_PUBLIC_PATH,
// Package and insert additional configuration files
injectConfig: isProdFn(mode)
? `<script src='${VITE_PUBLIC_PATH || './'}${GLOB_CONFIG_FILE_NAME}?v=${
pkg.version
}-${new Date().getTime()}'></script>`
: '',
// Insert Baidu statistics code
hmScript: isSiteMode() ? hmScript : '',
title: VITE_GLOB_APP_TITLE,
const htmlPlugin: Plugin[] = html({
minify: isBuild,
inject: {
injectData: {
title: VITE_GLOB_APP_TITLE,
},
tags: isBuild
? [
{
tag: 'script',
attrs: {
src: `${VITE_PUBLIC_PATH || './'}${GLOB_CONFIG_FILE_NAME}?v=${
pkg.version
}-${new Date().getTime()}`,
},
},
]
: [],
},
});
plugins.push(htmlPlugin);
return plugins;
return htmlPlugin;
}

View File

@@ -0,0 +1,12 @@
import dynamicImport from 'vite-plugin-import-context';
import type { ViteEnv } from '../../utils';
import type { Plugin } from 'vite';
export function configDynamicImport(env: ViteEnv) {
const { VITE_DYNAMIC_IMPORT } = env;
const dynamicImportPlugin: Plugin = dynamicImport({
include: ['**/*.ts'],
autoImportRoute: VITE_DYNAMIC_IMPORT,
});
return dynamicImportPlugin;
}

View File

@@ -1,47 +1,44 @@
import type { Plugin as VitePlugin } from 'vite';
import type { Plugin as rollupPlugin } from 'rollup';
import type { Plugin } from 'vite';
import PurgeIcons from 'vite-plugin-purge-icons';
import visualizer from 'rollup-plugin-visualizer';
import gzipPlugin from './gzip/index';
// @ts-ignore
import pkg from '../../../package.json';
import { isSiteMode, ViteEnv, isReportMode, isBuildGzip } from '../../utils';
import { setupHtmlPlugin } from './html';
import { setupPwaPlugin } from './pwa';
import { setupMockPlugin } from './mock';
import { ViteEnv, isReportMode } from '../../utils';
import { configHtmlPlugin } from './html';
import { configPwaConfig } from './pwa';
import { configMockPlugin } from './mock';
import { configDynamicImport } from './importContext';
import { configGzipPlugin } from './gzip';
// gen vite plugins
export function createVitePlugins(viteEnv: ViteEnv, mode: 'development' | 'production') {
const vitePlugins: VitePlugin[] = [];
export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean, mode: string) {
const vitePlugins: (Plugin | Plugin[])[] = [];
// vite-plugin-html
setupHtmlPlugin(vitePlugins, viteEnv, mode);
vitePlugins.push(configHtmlPlugin(viteEnv, isBuild));
// vite-plugin-pwa
setupPwaPlugin(vitePlugins, viteEnv, mode);
vitePlugins.push(configPwaConfig(viteEnv, isBuild));
// vite-plugin-mock
setupMockPlugin(vitePlugins, viteEnv, mode);
vitePlugins.push(configMockPlugin(viteEnv, isBuild));
// vite-plugin-import-context
vitePlugins.push(configDynamicImport(viteEnv));
// vite-plugin-purge-icons
vitePlugins.push(PurgeIcons());
// rollup-plugin-gzip
vitePlugins.push(configGzipPlugin(isBuild));
// rollup-plugin-visualizer
if (isReportMode()) {
vitePlugins.push(visualizer({ filename: './build/.cache/stats.html', open: true }) as Plugin);
}
return vitePlugins;
}
// gen rollup plugins
export function createRollupPlugin() {
const rollupPlugins: rollupPlugin[] = [];
if (isReportMode()) {
// rollup-plugin-visualizer
rollupPlugins.push(visualizer({ filename: './build/.cache/stats.html', open: true }) as Plugin);
}
if (isBuildGzip() || isSiteMode()) {
// rollup-plugin-gizp
rollupPlugins.push(gzipPlugin());
}
return rollupPlugins;
}

View File

@@ -1,24 +1,19 @@
import { createMockServer } from 'vite-plugin-mock';
import type { Plugin } from 'vite';
import { isDevFn, ViteEnv } from '../../utils';
import { viteMockServe } from 'vite-plugin-mock';
import { ViteEnv } from '../../utils';
export function setupMockPlugin(
plugins: Plugin[],
env: ViteEnv,
mode: 'development' | 'production'
) {
export function configMockPlugin(env: ViteEnv, isBuild: boolean) {
const { VITE_USE_MOCK } = env;
const useMock = isDevFn(mode) && VITE_USE_MOCK;
const useMock = !isBuild && VITE_USE_MOCK;
if (useMock) {
const mockPlugin = createMockServer({
const mockPlugin = viteMockServe({
ignore: /^\_/,
mockPath: 'mock',
showTime: true,
localEnabled: useMock,
});
plugins.push(mockPlugin);
return mockPlugin;
}
return plugins;
return [];
}

View File

@@ -1,35 +1,31 @@
import { VitePWA } from 'vite-plugin-pwa';
import type { Plugin } from 'vite';
import { ViteEnv } from '../../utils';
export function setupPwaPlugin(
plugins: Plugin[],
env: ViteEnv,
// @ts-ignore
mode: 'development' | 'production'
) {
const { VITE_USE_PWA } = env;
export function configPwaConfig(env: ViteEnv, isBulid: boolean) {
const { VITE_USE_PWA, VITE_GLOB_APP_TITLE, VITE_GLOB_APP_SHORT_NAME } = env;
const pwaPlugin = VitePWA({
manifest: {
name: 'Vben Admin',
short_name: 'vben_admin',
icons: [
{
src: './resource/img/pwa-192x192.png',
sizes: '192x192',
type: 'image/png',
},
{
src: './resource/img/pwa-512x512.png',
sizes: '512x512',
type: 'image/png',
},
],
},
});
if (VITE_USE_PWA) {
plugins.push(pwaPlugin);
if (VITE_USE_PWA && isBulid) {
// vite-plugin-pwa
const pwaPlugin = VitePWA({
manifest: {
name: VITE_GLOB_APP_TITLE,
short_name: VITE_GLOB_APP_SHORT_NAME,
icons: [
{
src: './resource/img/pwa-192x192.png',
sizes: '192x192',
type: 'image/png',
},
{
src: './resource/img/pwa-512x512.png',
sizes: '512x512',
type: 'image/png',
},
],
},
});
return pwaPlugin;
}
return plugins;
return [];
}

View File

@@ -1,54 +0,0 @@
// Used to import all files under `src/views`
// The built-in dynamic import of vite cannot meet the needs of importing all files under views
// Special usage Only for this project
import glob from 'glob';
import { Transform } from 'vite/dist/node/transform.js';
function getPath(path: string) {
const lastIndex = path.lastIndexOf('.');
if (lastIndex !== -1) {
path = path.substring(0, lastIndex);
}
return path.replace('src/views', '');
}
const dynamicImportTransform = function (enableDynamicImport: boolean): Transform {
return {
test({ path }) {
// Only convert the file
return (
path.includes('/src/router/helper/dynamicImport.ts') ||
path.includes(`\\src\\router\\helper\\dynamicImport.ts`)
);
},
transform({ code }) {
if (!enableDynamicImport) {
return code;
}
// Only convert the dir
try {
const files = glob.sync('src/views/**/**.{vue,tsx}', { cwd: process.cwd() });
return `
export default function (id) {
switch (id) {
${files
.map((p) =>
` case '${getPath(p)}': return () => import('${p
.replace('src/views', '/@/views')
.replace(/\/\//g, '/')}');`.replace('.tsx', '')
)
.join('\n ')}
default: return Promise.reject(new Error("Unknown variable dynamic import: " + id));
}
}\n\n
`;
} catch (error) {
console.error(error);
return code;
}
},
};
};
export default dynamicImportTransform;

View File

@@ -1,222 +0,0 @@
// Modified from
// https://github.com/luxueyan/vite-transform-globby-import/blob/master/src/index.ts
// TODO Deleting files requires re-running the project
import { join } from 'path';
import { lstatSync } from 'fs';
import glob from 'glob';
import globrex from 'globrex';
import dotProp from 'dot-prop';
import { createResolver, Resolver } from 'vite/dist/node/resolver.js';
import { Transform } from 'vite/dist/node/transform.js';
const modulesDir: string = join(process.cwd(), '/node_modules/');
interface SharedConfig {
root?: string;
alias?: Record<string, string>;
resolvers?: Resolver[];
includes?: string[];
}
function template(template: string) {
return (data: { [x: string]: any }) => {
return template.replace(/#([^#]+)#/g, (_, g1) => data[g1] || g1);
};
}
// TODO support hmr
function hmr(isBuild = false) {
if (isBuild) return '';
return `
if (import.meta.hot) {
import.meta.hot.accept();
}`;
}
// handle includes
function fileInclude(includes: string | string[] | undefined, filePath: string) {
return !includes || !Array.isArray(includes)
? true
: includes.some((item) => filePath.startsWith(item));
}
// Bare exporter
function compareString(modify: any, data: string[][]) {
return modify ? '\n' + data.map((v) => `${v[0]}._path = ${v[1]}`).join('\n') : '';
}
function varTemplate(data: string[][], name: string) {
//prepare deep data (for locales)
let deepData: Record<string, object | string> = {};
let hasDeepData = false;
//data modify
data.map((v) => {
//check for has deep data
if (v[0].includes('/')) {
hasDeepData = true;
}
// lastKey is a data
let pathValue = v[0].replace(/\//g, '.').split('.');
// let scopeKey = '';
// const len=pathValue.length
// const scope=pathValue[len-2]
let lastKey: string | undefined = pathValue.pop();
let deepValue: Record<any, any> = {};
if (lastKey) {
// Solve the problem of files with the same name in different folders
const lastKeyList = lastKey.replace('_' + pathValue[0], '').split('_');
const key = lastKeyList.pop();
if (key) {
deepValue[key] = lastKey;
}
}
// Set Deep Value
deepValue = Object.assign(deepValue, dotProp.get(deepData, pathValue.join('.')));
dotProp.set(deepData, pathValue.join('.'), deepValue);
});
if (hasDeepData) {
return `const ${name} = ` + JSON.stringify(deepData).replace(/\"|\'/g, '');
}
return `const ${name} = { ${data.map((v) => v[0]).join(',')} }`;
}
const globTransform = function (config: SharedConfig): Transform {
const resolver = createResolver(
config.root || process.cwd(),
config.resolvers || [],
config.alias || {}
);
const { includes } = config;
const cache = new Map();
const urlMap = new Map();
return {
test({ path }) {
const filePath = path.replace('\u0000', ''); // why some path startsWith '\u0000'?
try {
return (
!filePath.startsWith(modulesDir) &&
/\.(vue|js|jsx|ts|tsx)$/.test(filePath) &&
fileInclude(includes, filePath) &&
lstatSync(filePath).isFile()
);
} catch {
return false;
}
},
transform({ code, path, isBuild }) {
let result = cache.get(path);
if (!result) {
const reg = /import\s+([\w\s{}*]+)\s+from\s+(['"])globby(\?locale)?(\?path)?!([^'"]+)\2/g;
const match = code.match(reg);
if (!match) return code;
const lastImport = urlMap.get(path);
if (lastImport && match) {
code = code.replace(lastImport, match[0]);
}
result = code.replace(
reg,
(
_,
// variable to export
exportName,
// bare export or not
bareExporter,
// is locale import
isLocale,
// inject _path attr
injectPath,
// path export
globPath
) => {
const filePath = path.replace('\u0000', ''); // why some path startsWith '\u0000'?
// resolve path
const resolvedFilePath = globPath.startsWith('.')
? resolver.resolveRelativeRequest(filePath, globPath)
: { pathname: resolver.requestToFile(globPath) };
const files = glob.sync(resolvedFilePath.pathname, { dot: true });
let templateStr = 'import #name# from #file#'; // import default
let name = exportName;
const m = exportName.match(/\{\s*(\w+)(\s+as\s+(\w+))?\s*\}/); // import module
const m2 = exportName.match(/\*\s+as\s+(\w+)/); // import * as all module
if (m) {
templateStr = `import { ${m[1]} as #name# } from #file#`;
name = m[3] || m[1];
} else if (m2) {
templateStr = 'import * as #name# from #file#';
name = m2[1];
}
const templateRender = template(templateStr);
const groups: Array<string>[] = [];
const replaceFiles = files.map((f, i) => {
const filePath = resolver.fileToRequest(f);
const file = bareExporter + filePath + bareExporter;
if (isLocale) {
const globrexRes = globrex(globPath, { extended: true, globstar: true });
// Get segments for files like an en/system ch/modules for:
// ['en', 'system'] ['ch', 'modules']
// TODO The window system and mac system path are inconsistent
const fileNameWithAlias = filePath.replace(/^(\/src\/)/, '/@/');
const matchedGroups = globrexRes.regex.exec(fileNameWithAlias);
if (matchedGroups && matchedGroups.length) {
const matchedSegments = matchedGroups[1]; //first everytime "Full Match"
const matchList = matchedSegments.split('/').filter(Boolean);
const lang = matchList.shift();
const scope = matchList.pop();
// Solve the problem of files with the same name in different folders
const scopeKey = scope ? `${scope}_` : '';
const fileName = matchedGroups[2];
const name = scopeKey + fileName + '_' + lang;
//send deep way like an (en/modules/system/dashboard) into groups
groups.push([matchedSegments + name, file]);
return templateRender({
name,
file,
});
}
} else {
groups.push([name + i, file]);
return templateRender({ name: name + i, file });
}
});
// save in memory used result
const filesJoined = replaceFiles.join('\n');
urlMap.set(path, filesJoined);
// console.log('======================');
// console.log(filesJoined, varTemplate(groups, name));
// console.log('======================');
return [
filesJoined,
compareString(injectPath, groups),
varTemplate(groups, name),
'',
].join('\n');
}
);
if (isBuild) cache.set(path, result);
}
return `${result}${hmr(isBuild)}`;
},
};
};
export default globTransform;

View File

@@ -1,16 +1,10 @@
import type { ServerOptions } from 'http-proxy';
type ProxyItem = [string, string];
type ProxyList = ProxyItem[];
type ProxyTargetList = Record<
string,
{
target: string;
changeOrigin: boolean;
rewrite: (path: string) => any;
secure?: boolean;
}
>;
type ProxyTargetList = Record<string, ServerOptions & { rewrite: (path: string) => string }>;
const httpsRE = /^https:\/\//;
@@ -23,9 +17,11 @@ export function createProxy(list: ProxyList = []) {
for (const [prefix, target] of list) {
const isHttps = httpsRE.test(target);
// https://github.com/http-party/node-http-proxy#options
ret[prefix] = {
target: target,
changeOrigin: true,
ws: true,
rewrite: (path) => path.replace(new RegExp(`^${prefix}`), ''),
// https is require secure=false
...(isHttps ? { secure: false } : {}),