解决方法一
plugin/naive-ui.ts
import { setup } from "@css-render/vue3-ssr";
import { defineNuxtPlugin } from "#app";
import fs from 'fs';
export default defineNuxtPlugin(nuxtApp => {
if (process.server) {
const { collect } = setup(nuxtApp.vueApp);
const originalRenderMeta = nuxtApp.ssrContext?.renderMeta;
nuxtApp.ssrContext = (nuxtApp.ssrContext as any) || {};
//解决样式加载缓慢问题
nuxtApp.ssrContext?.head.hooks.hook('tags:resolve', (ctx) => {
const styles = collect();
const regex = /<style[^>]*>([\s\S]*?)<\/style>/g;
let matches;
const extractedStyles = [];
while ((matches = regex.exec(styles)) !== null) {
extractedStyles.push(matches[1].trim());
}
const concatenatedStyles = extractedStyles.join('\n');
console.log('s',concatenatedStyles)
fs.writeFile('assets/css/naive.css', concatenatedStyles, (err) => {
if (err) {
console.error('Error writing CSS file:', err);
}
});
})
nuxtApp.ssrContext!.renderMeta = () => {
if (!originalRenderMeta) {
return {
headTags: collect()
};
}
const originalMeta = originalRenderMeta();
if ("then" in originalMeta) {
return originalMeta.then((resolvedOriginalMeta:any) => {
return {
...resolvedOriginalMeta,
headTags: resolvedOriginalMeta.headTags + collect()
};
});
} else {
return {
...originalMeta,
headTags: originalMeta.headTags + collect()
};
}
};
}
});
nuxt.config.ts
要有assets/css这个目录
css: ["~/assets/css/naive.css"]
第二种方法
plugin/naive-ui.ts
export default defineNuxtPlugin({
name: 'naive-ui',
enforce: 'pre',
setup(nuxtApp) {
if (process.server) {
const { collect } = setup(nuxtApp.vueApp)
nuxtApp.ssrContext?.head.hooks.hook('tags:resolve', (ctx) => {
// insert Style after meta
const lastMetaIndex = ctx.tags.map(x => x.tag).lastIndexOf('meta')
const styleTags = collect().split('</style>').filter(Boolean).map(x => {
const id = x.match(/cssr-id="(.+?)"/)?.[1]
const style = (x.match(/>(.*)/s)?.[1] || '').trim()
return {
tag: 'style',
props: {'cssr-id': id},
innerHTML: style
}
})
ctx.tags.splice(lastMetaIndex+1, 0, ...styleTags)
})
}
}
})
我遇到的场景是在用naive的表单组件时,用了上面的方法还是会存在刷新有label-width的宽度会变化,找到的原因是label-width设置为auto,我这里给他设置了一个具体的宽度
<n-form
ref="formRef"
:model="formData"
:rules="rules"
label-placement="left"
:label-width="60"
:show-require-mark="false"
size="medium"
:style="{
maxWidth: '500px'
}"
>
<n-form-item label="账号" path="account">
<n-input v-model:value="formData.account" placeholder="请输入账号" />
</n-form-item>
<n-form-item label="密码" path="password">
<n-input v-model:value="formData.password" type="password" show-password-on="mousedown" placeholder="请输入密码" />
</n-form-item>
<n-form-item label="验证码" path="code">
<div class="flex justify-between w-100%">
<n-input v-model:value="formData.code" style="max-width: 50%" placeholder="请输入验证码" />
<img src="@/assets/images/semiroc-logo.png" alt="" class="w-[120px] h-9 ml-4">
</div>
</n-form-item>
</n-form>
这个问题就解决了。