Files

92 lines
3.1 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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,
},
});