mirror of
https://github.com/WeBankFinTech/fes.js.git
synced 2025-04-06 03:59:53 +08:00
feat: 完善 vite build
This commit is contained in:
parent
f9397495c4
commit
51ebe58a29
@ -1,29 +1,47 @@
|
||||
import legacy from '@vitejs/plugin-legacy';
|
||||
import { getInnerCommonConfig } from '../../common/getConfig';
|
||||
|
||||
/**
|
||||
* polyfill: @vitejs/plugin-legacy
|
||||
* 确认 css 最终构建实现 autoprefixer postcss-safe-parser postcss-flexbugs-fixes
|
||||
*/
|
||||
|
||||
export default async (api) => {
|
||||
const { deepmerge } = api.utils;
|
||||
const { deepmerge, getTargetsAndBrowsersList } = api.utils;
|
||||
|
||||
const { build = {} } = api.config.viteOption;
|
||||
const { browserslist } = getTargetsAndBrowsersList({ config: api.config });
|
||||
|
||||
return deepmerge(
|
||||
const bundleConfig = deepmerge(
|
||||
{
|
||||
mode: 'production',
|
||||
css: {
|
||||
postcss: {
|
||||
plugins: [require('postcss-flexbugs-fixes'), require('postcss-safe-parser'), [require('autoprefixer'), {}]],
|
||||
plugins: [
|
||||
require('postcss-flexbugs-fixes'),
|
||||
require('postcss-safe-parser'),
|
||||
require('autoprefixer')({
|
||||
...api.config.autoprefixer,
|
||||
overrideBrowserslist: browserslist,
|
||||
}),
|
||||
],
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
legacy({
|
||||
targets: browserslist,
|
||||
...api.config.viteLegacy,
|
||||
}),
|
||||
],
|
||||
build: {
|
||||
...build,
|
||||
target: build.target || 'es2015',
|
||||
outDir: build.outDir || api.config.outputPath || 'dist',
|
||||
assetsInlineLimit: build.assetsInlineLimit || api.config.inlineLimit || 8192,
|
||||
},
|
||||
},
|
||||
getInnerCommonConfig(api),
|
||||
);
|
||||
|
||||
return api.applyPlugins({
|
||||
type: api.ApplyPluginsType.modify,
|
||||
key: 'modifyBundleConfig',
|
||||
initialValue: bundleConfig,
|
||||
args: {},
|
||||
});
|
||||
};
|
||||
|
@ -24,12 +24,13 @@ export default async (api, args) => {
|
||||
args: {},
|
||||
});
|
||||
|
||||
return deepmerge(
|
||||
const bundleConfig = deepmerge(
|
||||
{
|
||||
mode: 'development',
|
||||
plugins: [viteMiddlewarePlugin(beforeMiddlewares, middlewares)],
|
||||
server: {
|
||||
...server,
|
||||
proxy: server?.proxy || api.config.proxy,
|
||||
port,
|
||||
host: hostname,
|
||||
https: process.env.HTTPS || args.https,
|
||||
@ -37,4 +38,11 @@ export default async (api, args) => {
|
||||
},
|
||||
getInnerCommonConfig(api),
|
||||
);
|
||||
|
||||
return api.applyPlugins({
|
||||
type: api.ApplyPluginsType.modify,
|
||||
key: 'modifyBundleConfig',
|
||||
initialValue: bundleConfig,
|
||||
args: {},
|
||||
});
|
||||
};
|
||||
|
@ -3,11 +3,6 @@ import getDevConfig from './getDevConfig';
|
||||
|
||||
/**
|
||||
* TODO
|
||||
|
||||
*
|
||||
* analyze: rollup-plugin-visualizer
|
||||
*
|
||||
* 其他插件如何对内部配置进行修改
|
||||
*
|
||||
* 共享 webpack 和 vite 的部分配置,降低熟悉 vite 的成本
|
||||
*/
|
||||
|
@ -5,11 +5,8 @@ import { createHtmlPlugin } from 'vite-plugin-html';
|
||||
import SFCConfigBlockPlugin from './SFCConfigBlockPlugin';
|
||||
import getDefine from './getDefine';
|
||||
|
||||
// TODO
|
||||
// * 如何处理 html (改 mountId or title 等)(比较麻烦,晚点再看看有无更好的方案)
|
||||
|
||||
export function getInnerCommonConfig(api) {
|
||||
const { deepmerge } = api.utils;
|
||||
const { deepmerge, resolveRuntimeEnv } = api.utils;
|
||||
const { server, build, define, base, ...otherViteOption } = api.config.viteOption;
|
||||
|
||||
const publicPath = base || api.config.publicPath || '/';
|
||||
@ -27,10 +24,10 @@ export function getInnerCommonConfig(api) {
|
||||
createHtmlPlugin({
|
||||
minify: true,
|
||||
entry: join(api.paths.absTmpPath, 'fes.js'),
|
||||
template: 'public/index.html',
|
||||
template: 'index.html',
|
||||
inject: {
|
||||
data: {
|
||||
title: 'Fes.js',
|
||||
...resolveRuntimeEnv(publicPath),
|
||||
mountElementId: api.config.mountElementId,
|
||||
},
|
||||
},
|
||||
|
@ -3,10 +3,24 @@ export default (api) => {
|
||||
key: 'viteAnalyze',
|
||||
config: {
|
||||
schema(joi) {
|
||||
return joi.object({}).unknown(true);
|
||||
return joi.object();
|
||||
},
|
||||
default: {},
|
||||
},
|
||||
enableBy: () => !!process.env.ANALYZE,
|
||||
});
|
||||
|
||||
api.modifyBundleConfig((memo) => {
|
||||
memo.plugins.push(
|
||||
require('rollup-plugin-visualizer').visualizer({
|
||||
filename: './.cache/visualizer/stats.html',
|
||||
open: true,
|
||||
gzipSize: true,
|
||||
brotliSize: true,
|
||||
...api.viteAnalyze,
|
||||
}),
|
||||
);
|
||||
|
||||
return memo;
|
||||
});
|
||||
};
|
||||
|
12
packages/fes-build-vite/src/features/viteHtml.js
Normal file
12
packages/fes-build-vite/src/features/viteHtml.js
Normal file
@ -0,0 +1,12 @@
|
||||
export default (api) => {
|
||||
api.describe({
|
||||
key: 'viteHtml',
|
||||
config: {
|
||||
schema(joi) {
|
||||
return joi.object();
|
||||
},
|
||||
default: {},
|
||||
},
|
||||
enableBy: () => !!process.env.ANALYZE,
|
||||
});
|
||||
};
|
12
packages/fes-build-vite/src/features/viteLegacy.js
Normal file
12
packages/fes-build-vite/src/features/viteLegacy.js
Normal file
@ -0,0 +1,12 @@
|
||||
export default (api) => {
|
||||
api.describe({
|
||||
key: 'viteLegacy',
|
||||
config: {
|
||||
schema(joi) {
|
||||
return joi.object();
|
||||
},
|
||||
default: {},
|
||||
},
|
||||
enableBy: () => !!process.env.ANALYZE,
|
||||
});
|
||||
};
|
@ -1,10 +1,15 @@
|
||||
export default function () {
|
||||
return {
|
||||
plugins: [
|
||||
require.resolve('./registerMethods'),
|
||||
require.resolve('./registerType'),
|
||||
|
||||
// bundle configs
|
||||
require.resolve('./features/viteOption'),
|
||||
require.resolve('./features/viteVueJsx'),
|
||||
require.resolve('./features/viteVuePlugin'),
|
||||
require.resolve('./features/viteAnalyze'),
|
||||
require.resolve('./features/viteLegacy'),
|
||||
|
||||
// commands
|
||||
require.resolve('./commands/build'),
|
||||
|
5
packages/fes-build-vite/src/registerMethods.js
Normal file
5
packages/fes-build-vite/src/registerMethods.js
Normal file
@ -0,0 +1,5 @@
|
||||
export default function (api) {
|
||||
['modifyBundleConfig'].forEach((name) => {
|
||||
api.registerMethod({ name });
|
||||
});
|
||||
}
|
8
packages/fes-build-vite/src/registerType.js
Normal file
8
packages/fes-build-vite/src/registerType.js
Normal file
@ -0,0 +1,8 @@
|
||||
import { name } from '../package.json';
|
||||
|
||||
export default function (api) {
|
||||
api.addConfigType(() => ({
|
||||
source: name,
|
||||
build: ['ViteBuildConfig'],
|
||||
}));
|
||||
}
|
4
packages/fes-build-vite/types.d.ts
vendored
4
packages/fes-build-vite/types.d.ts
vendored
@ -1,10 +1,14 @@
|
||||
import type {UserConfig} from 'vite';
|
||||
import type {Options} from '@vitejs/plugin-vue'
|
||||
import {Options as PolyfillOptions } from '@vitejs/plugin-legacy'
|
||||
import createPlugin from '@vitejs/plugin-vue-jsx'
|
||||
import {createHtmlPlugin} from 'vite-plugin-html'
|
||||
|
||||
|
||||
export interface ViteBuildConfig {
|
||||
viteOption: UserConfig;
|
||||
viteVuePlugin: Options;
|
||||
viteVueJsx: Parameters<typeof createPlugin>[0];
|
||||
viteLegacy: PolyfillOptions;
|
||||
viteHtml: Parameters<typeof createHtmlPlugin>[0]
|
||||
}
|
||||
|
@ -25,7 +25,6 @@ export default function () {
|
||||
require.resolve('./plugins/features/outputPath'),
|
||||
require.resolve('./plugins/features/postcssLoader'),
|
||||
require.resolve('./plugins/features/publicPath'),
|
||||
require.resolve('./plugins/features/targets'),
|
||||
require.resolve('./plugins/features/terserOptions'),
|
||||
require.resolve('./plugins/features/nodeModulesTransform'),
|
||||
require.resolve('./plugins/features/vueLoader'),
|
||||
|
@ -167,8 +167,6 @@ export function printFileSizes(stats, dir) {
|
||||
console.log(`${ui.toString()}\n\n ${chalk.gray('Images and other types of assets omitted.')}\n`);
|
||||
|
||||
if (orderedAssets?.some((asset) => asset.suggested)) {
|
||||
// We'll warn for bundles exceeding them.
|
||||
// TODO: use umi docs
|
||||
console.log();
|
||||
console.log(chalk.yellow('The bundle size is significantly larger than recommended.'));
|
||||
console.log(chalk.yellow('Consider reducing it with code splitting'));
|
||||
|
@ -9,24 +9,6 @@ import createDefineWebpackConfig from './define';
|
||||
import createMinimizerWebpackConfig from './minimizer';
|
||||
import createHtmlWebpackConfig from './html';
|
||||
|
||||
function getTargetsAndBrowsersList({ config }) {
|
||||
let targets = config.targets || {};
|
||||
|
||||
targets = Object.keys(targets)
|
||||
.filter((key) => targets[key] !== false)
|
||||
.reduce((memo, key) => {
|
||||
memo[key] = targets[key];
|
||||
return memo;
|
||||
}, {});
|
||||
|
||||
const browserslist = targets.browsers || Object.keys(targets).map((key) => `${key} >= ${targets[key] === true ? '0' : targets[key]}`);
|
||||
|
||||
return {
|
||||
targets,
|
||||
browserslist,
|
||||
};
|
||||
}
|
||||
|
||||
const DEFAULT_EXCLUDE_NODE_MODULES = [
|
||||
'vue',
|
||||
'vuex',
|
||||
@ -139,7 +121,7 @@ export default async function getConfig({ api, cwd, config, env, entry = {}, mod
|
||||
esModule: false,
|
||||
});
|
||||
|
||||
const { targets, browserslist } = getTargetsAndBrowsersList({ config });
|
||||
const { targets, browserslist } = api.utils.getTargetsAndBrowsersList({ config });
|
||||
const babelOpts = await getBabelOpts({
|
||||
cwd,
|
||||
config,
|
||||
|
@ -15,8 +15,6 @@ import mergeDefault from './utils/mergeDefault';
|
||||
|
||||
const CONFIG_FILES = ['.fes.js'];
|
||||
|
||||
// TODO:
|
||||
// 1. custom config file
|
||||
export default class Config {
|
||||
cwd;
|
||||
|
||||
|
@ -21,6 +21,7 @@ export default function () {
|
||||
require.resolve('./plugins/features/plugins'),
|
||||
require.resolve('./plugins/features/proxy'),
|
||||
require.resolve('./plugins/features/singular'),
|
||||
require.resolve('./plugins/features/targets'),
|
||||
|
||||
// route
|
||||
require.resolve('./plugins/route'),
|
||||
|
@ -2,13 +2,16 @@ import { extname } from 'path';
|
||||
import historyFallback from 'connect-history-api-fallback';
|
||||
|
||||
const ASSET_EXT_NAMES = ['.ico', '.png', '.jpg', '.jpeg', '.gif', '.svg'];
|
||||
const SKIP_PATHS_PREFIX = ['/@vite', '/@id'];
|
||||
|
||||
const proxyMiddleware = (api) => (req, res, next) => {
|
||||
const proxyConfig = api.config.proxy;
|
||||
if (proxyConfig && Object.keys(proxyConfig).some((path) => req.url.startsWith(path))) {
|
||||
return next();
|
||||
}
|
||||
|
||||
if (SKIP_PATHS_PREFIX.find((prefix) => req.url.startsWith(prefix))) {
|
||||
return next();
|
||||
}
|
||||
if (ASSET_EXT_NAMES.includes(extname(req.url))) {
|
||||
return next();
|
||||
}
|
||||
|
@ -3,11 +3,10 @@ export default (api) => {
|
||||
key: 'targets',
|
||||
config: {
|
||||
default: {
|
||||
chrome: 49,
|
||||
firefox: 64,
|
||||
safari: 10,
|
||||
chrome: 56,
|
||||
firefox: 67,
|
||||
safari: 10.4,
|
||||
edge: 13,
|
||||
ios: 10,
|
||||
},
|
||||
schema(joi) {
|
||||
return joi.object();
|
@ -1,4 +1,3 @@
|
||||
// TODO 其他 API
|
||||
export {
|
||||
useRoute,
|
||||
useRouter,
|
||||
@ -10,7 +9,7 @@ export {
|
||||
createWebHashHistory,
|
||||
createWebHistory,
|
||||
createMemoryHistory,
|
||||
createRouter
|
||||
createRouter,
|
||||
} from 'vue-router';
|
||||
|
||||
export { default as Plugin, ApplyPluginsType } from './plugin';
|
||||
|
@ -11,15 +11,12 @@
|
||||
<meta name="viewport"
|
||||
content="viewport-fit=cover,width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no">
|
||||
<title>
|
||||
<%= title %>
|
||||
Fes & vite
|
||||
</title>
|
||||
<link rel="shortcut icon" type="image/x-icon" href="./logo.png">
|
||||
</head>
|
||||
|
||||
<body ontouchstart="">
|
||||
<div id="<%= mountElementId %>"></div>
|
||||
<script type="module" src="/src/.fes/fes.js"></script>
|
||||
<!-- built files will be auto injected -->
|
||||
</body>
|
||||
|
||||
</html>
|
@ -4,7 +4,8 @@
|
||||
"description": "fes vite 构建模版",
|
||||
"scripts": {
|
||||
"prod": "FES_ENV=prod fes build",
|
||||
"dev": "fes dev"
|
||||
"dev": "fes dev",
|
||||
"analyze": "ANALYZE=1 fes build"
|
||||
},
|
||||
"keywords": [
|
||||
"管理端",
|
||||
|
@ -1,4 +1,3 @@
|
||||
// TODO
|
||||
// 时间格式化
|
||||
// js 数字精度计算
|
||||
// 手机号、身份证号 等的校验
|
||||
|
17
packages/fes-utils/src/getTargetsAndBrowsersList.js
Normal file
17
packages/fes-utils/src/getTargetsAndBrowsersList.js
Normal file
@ -0,0 +1,17 @@
|
||||
export default function getTargetsAndBrowsersList({ config }) {
|
||||
let targets = config.targets || {};
|
||||
|
||||
targets = Object.keys(targets)
|
||||
.filter((key) => targets[key] !== false)
|
||||
.reduce((memo, key) => {
|
||||
memo[key] = targets[key];
|
||||
return memo;
|
||||
}, {});
|
||||
|
||||
const browserslist = targets.browsers || Object.keys(targets).map((key) => `${key} >= ${targets[key] === true ? '0' : targets[key]}`);
|
||||
|
||||
return {
|
||||
targets,
|
||||
browserslist,
|
||||
};
|
||||
}
|
@ -31,6 +31,7 @@ import changePort from './changePort';
|
||||
import getHostName from './getHostName';
|
||||
import resolveRuntimeEnv from './resolveRuntimeEnv';
|
||||
import stringifyObjValue from './stringifyObjValue';
|
||||
import getTargetsAndBrowsersList from './getTargetsAndBrowsersList';
|
||||
|
||||
export {
|
||||
chalk,
|
||||
@ -68,4 +69,5 @@ export {
|
||||
getHostName,
|
||||
resolveRuntimeEnv,
|
||||
stringifyObjValue,
|
||||
getTargetsAndBrowsersList,
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user