92 lines
3.1 KiB
TypeScript
92 lines
3.1 KiB
TypeScript
import { defineConfig, type Plugin } from 'vite';
|
||
import react from '@vitejs/plugin-react';
|
||
import libAssetsPlugin from '@laynezh/vite-plugin-lib-assets';
|
||
import { resolve, dirname } from 'path';
|
||
import { fileURLToPath } from 'url';
|
||
|
||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||
|
||
/**
|
||
* 去掉 fontsource CSS 里的 woff 备份,只保留 woff2。
|
||
* 现代浏览器(Chrome 36+/Firefox 39+/Safari 10+/Edge 14+)100% 支持 woff2。
|
||
* 产物 dist/files/ 体积可进一步降低 ~40%。
|
||
*/
|
||
function stripWoffFallbackPlugin(): Plugin {
|
||
return {
|
||
name: 'strip-woff-fallback',
|
||
enforce: 'pre',
|
||
transform(code, id) {
|
||
if (!id.includes('@fontsource')) return null;
|
||
if (!id.endsWith('.css') && !/\.css\?/.test(id)) return null;
|
||
const transformed = code.replace(
|
||
/,\s*url\([^)]+\.woff\)\s*format\(['"]woff['"]\)/g,
|
||
'',
|
||
);
|
||
return transformed === code ? null : { code: transformed, map: null };
|
||
},
|
||
// libAssetsPlugin 会独立扫描源 CSS 并 emit 所有 url() 引用的文件(包括被我们剥掉的 woff),
|
||
// 在 bundle 阶段删除未被最终 CSS 引用的 woff 孤儿文件。
|
||
generateBundle(_, bundle) {
|
||
for (const key of Object.keys(bundle)) {
|
||
const asset = bundle[key];
|
||
if (asset.type === 'asset' && /\.woff$/i.test(key)) {
|
||
delete bundle[key];
|
||
}
|
||
}
|
||
},
|
||
};
|
||
}
|
||
|
||
export default defineConfig({
|
||
plugins: [
|
||
react(),
|
||
stripWoffFallbackPlugin(),
|
||
// lib 模式下 Vite 会强制内联所有资源,本插件绕过该限制,把字体/图片等作为独立文件输出
|
||
libAssetsPlugin({
|
||
outputPath: 'files',
|
||
name: '[name].[contenthash:8].[ext]',
|
||
limit: 0,
|
||
}),
|
||
],
|
||
resolve: {
|
||
alias: {
|
||
'@': resolve(__dirname, 'src'),
|
||
},
|
||
},
|
||
css: {
|
||
modules: {
|
||
// 生成类名格式:animal-[类名]-[hash]
|
||
generateScopedName: 'animal-[local]-[hash:base64:5]',
|
||
localsConvention: 'camelCase',
|
||
},
|
||
preprocessorOptions: {
|
||
less: {
|
||
javascriptEnabled: true,
|
||
additionalData: `@import "${resolve(__dirname, 'src/styles/variables.less')}";`,
|
||
},
|
||
},
|
||
},
|
||
build: {
|
||
lib: {
|
||
entry: resolve(__dirname, 'src/index.ts'),
|
||
formats: ['es', 'cjs'],
|
||
fileName: (format) =>
|
||
`${format === 'es' ? 'es' : 'cjs'}/index.${format === 'es' ? 'js' : 'cjs'}`,
|
||
},
|
||
rollupOptions: {
|
||
external: ['react', 'react-dom', 'react/jsx-runtime'],
|
||
output: {
|
||
globals: {
|
||
react: 'React',
|
||
'react-dom': 'ReactDOM',
|
||
},
|
||
assetFileNames: (assetInfo) => {
|
||
if (assetInfo.name?.endsWith('.css')) return 'index.css';
|
||
return assetInfo.name!;
|
||
},
|
||
},
|
||
},
|
||
cssCodeSplit: false,
|
||
},
|
||
});
|