Open JackFGreen opened 3 years ago
I have the same problem which I suffer from..
Me too
Me too
I encountered the same problem, css cannot be loaded correctly when building lib mode.
I created a plugin to temporarily solve this problem.
import fs from 'fs'
import { resolve } from 'path'
import type { ResolvedConfig, PluginOption } from 'vite'
const fileRegex = /\.(css)$/
const injectCode = (code: string) =>
`function styleInject(css,ref){if(ref===void 0){ref={}}var insertAt=ref.insertAt;if(!css||typeof document==="undefined"){return}var head=document.head||document.getElementsByTagName("head")[0];var style=document.createElement("style");style.type="text/css";if(insertAt==="top"){if(head.firstChild){head.insertBefore(style,head.firstChild)}else{head.appendChild(style)}}else{head.appendChild(style)}if(style.styleSheet){style.styleSheet.cssText=css}else{style.appendChild(document.createTextNode(css))}};styleInject(\`${code}\`)`
const template = `console.warn("__INJECT__")`
let viteConfig: ResolvedConfig
const css: string[] = []
export default function libInjectCss(): PluginOption {
return {
name: 'lib-inject-css',
apply: 'build',
configResolved(resolvedConfig: ResolvedConfig) {
viteConfig = resolvedConfig
},
transform(code: string, id: string) {
if (fileRegex.test(id)) {
css.push(code)
return {
code: '',
}
}
if (
// @ts-ignore
id.includes(viteConfig.build.lib.entry)
) {
return {
code: `${code}
${template}`,
}
}
return null
},
async writeBundle(_: any, bundle: any) {
for (const file of Object.entries(bundle)) {
const { root } = viteConfig
const outDir: string = viteConfig.build.outDir || 'dist'
const fileName: string = file[0]
const filePath: string = resolve(root, outDir, fileName)
try {
let data: string = fs.readFileSync(filePath, {
encoding: 'utf8',
})
if (data.includes(template)) {
data = data.replace(template, injectCode(css.join('\n')))
}
fs.writeFileSync(filePath, data)
} catch (e) {
console.error(e)
}
}
},
}
}
https://github.com/ohbug-org/ohbug-extension-feedback/blob/main/libInjectCss.ts
I encountered the same problem, css cannot be loaded correctly when building lib mode.
I created a plugin to temporarily solve this problem.
import fs from 'fs' import { resolve } from 'path' import type { ResolvedConfig, PluginOption } from 'vite' const fileRegex = /\.(css)$/ const injectCode = (code: string) => `function styleInject(css,ref){if(ref===void 0){ref={}}var insertAt=ref.insertAt;if(!css||typeof document==="undefined"){return}var head=document.head||document.getElementsByTagName("head")[0];var style=document.createElement("style");style.type="text/css";if(insertAt==="top"){if(head.firstChild){head.insertBefore(style,head.firstChild)}else{head.appendChild(style)}}else{head.appendChild(style)}if(style.styleSheet){style.styleSheet.cssText=css}else{style.appendChild(document.createTextNode(css))}};styleInject(\`${code}\`)` const template = `console.warn("__INJECT__")` let viteConfig: ResolvedConfig const css: string[] = [] export default function libInjectCss(): PluginOption { return { name: 'lib-inject-css', apply: 'build', configResolved(resolvedConfig: ResolvedConfig) { viteConfig = resolvedConfig }, transform(code: string, id: string) { if (fileRegex.test(id)) { css.push(code) return { code: '', } } if ( // @ts-ignore id.includes(viteConfig.build.lib.entry) ) { return { code: `${code} ${template}`, } } return null }, async writeBundle(_: any, bundle: any) { for (const file of Object.entries(bundle)) { const { root } = viteConfig const outDir: string = viteConfig.build.outDir || 'dist' const fileName: string = file[0] const filePath: string = resolve(root, outDir, fileName) try { let data: string = fs.readFileSync(filePath, { encoding: 'utf8', }) if (data.includes(template)) { data = data.replace(template, injectCode(css.join('\n'))) } fs.writeFileSync(filePath, data) } catch (e) { console.error(e) } } }, } }
https://github.com/ohbug-org/ohbug-extension-feedback/blob/main/libInjectCss.ts
How to use it? install a npm?
I encountered the same problem, css cannot be loaded correctly when building lib mode. I created a plugin to temporarily solve this problem.
import fs from 'fs' import { resolve } from 'path' import type { ResolvedConfig, PluginOption } from 'vite' const fileRegex = /\.(css)$/ const injectCode = (code: string) => `function styleInject(css,ref){if(ref===void 0){ref={}}var insertAt=ref.insertAt;if(!css||typeof document==="undefined"){return}var head=document.head||document.getElementsByTagName("head")[0];var style=document.createElement("style");style.type="text/css";if(insertAt==="top"){if(head.firstChild){head.insertBefore(style,head.firstChild)}else{head.appendChild(style)}}else{head.appendChild(style)}if(style.styleSheet){style.styleSheet.cssText=css}else{style.appendChild(document.createTextNode(css))}};styleInject(\`${code}\`)` const template = `console.warn("__INJECT__")` let viteConfig: ResolvedConfig const css: string[] = [] export default function libInjectCss(): PluginOption { return { name: 'lib-inject-css', apply: 'build', configResolved(resolvedConfig: ResolvedConfig) { viteConfig = resolvedConfig }, transform(code: string, id: string) { if (fileRegex.test(id)) { css.push(code) return { code: '', } } if ( // @ts-ignore id.includes(viteConfig.build.lib.entry) ) { return { code: `${code} ${template}`, } } return null }, async writeBundle(_: any, bundle: any) { for (const file of Object.entries(bundle)) { const { root } = viteConfig const outDir: string = viteConfig.build.outDir || 'dist' const fileName: string = file[0] const filePath: string = resolve(root, outDir, fileName) try { let data: string = fs.readFileSync(filePath, { encoding: 'utf8', }) if (data.includes(template)) { data = data.replace(template, injectCode(css.join('\n'))) } fs.writeFileSync(filePath, data) } catch (e) { console.error(e) } } }, } }
https://github.com/ohbug-org/ohbug-extension-feedback/blob/main/libInjectCss.ts
How to use it? install a npm?
// vite.config.ts
import { defineConfig } from 'vite'
import libInjectCss from './libInjectCss'
export default defineConfig({
plugins: [
libInjectCss(),
],
})
Here is a sample file: https://github.com/ohbug-org/ohbug-extension-feedback/blob/main/vite.config.ts
i cant really find a sustainable way to make the styles inline in lib mode... my lib is used in more then 5 place.. and expected to grow.. and i don't want to manually import style file everywhere.. so wanted to include as build itself...
is vite going proposed any solution ? 🤔
Same here. To me as a vue user, vue-cli's extract: false
works fine in lib mode. https://cli.vuejs.org/config/#css-extract
I am wondering if vite does not have the option on purpose. But any solution would be needed.
Excuse me, is there a solution to this problem?
Excuse me, is there a solution to this problem?
I wrote a vite plugin:
https://github.com/ruofee/vue-dynamic-form-component/blob/vite/build/ViteSingleCssPlugin.js
Both plugins shared above did not work for me... and I am still looking for a solution...
Both plugins shared above did not work for me... and I am still looking for a solution...
You can check adjacent 2 comments at https://github.com/vitejs/vite/issues/1579#issuecomment-1482683935
Is this feature still relevant for Vite ? If yes, I can try to develop it.
Hi. I'm developing a UI kit. At the moment I use vue-cli
and I can't switch to vite
because of this problem.
Hey, I created a PR for this #13565. Feel free to look into it.
@marcelobotega thank you for building this! It will be very helpful!
Do you know when #13565 might get merged?
Hey @tibineagu, sadly I do not have the time to update the PR right now (could not find a way to make the legacy work with multiple entries), but we ended using this solution on our library and worked better than the cssExtract
option.
I'll leave the vite.config file here in case anyone want to check it out.
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import { visualizer } from 'rollup-plugin-visualizer';
import { PluginPure } from 'rollup-plugin-pure';
import { createRequire } from 'module';
import { libInjectCss } from 'vite-plugin-lib-inject-css';
import { extname, relative } from 'path';
import { fileURLToPath } from 'node:url';
import { glob } from 'glob';
const require = createRequire(import.meta.url);
const pkg = require('./package.json');
const external = Object.keys(pkg.dependencies);
export default defineConfig({
optimizeDeps: {
exclude: ['vue-demi'],
},
plugins: [
vue(),
libInjectCss(),
PluginPure({
functions: ['defineComponent'],
sourcemap: true,
}),
{
...visualizer({ template: 'sunburst', sourcemap: true }),
apply: 'build',
},
],
outDir: './dist',
build: {
cssCodeSplit: true,
sourcemap: true,
lib: {
entry: ['main.js'],
formats: ['es'],
},
rollupOptions: {
// https://rollupjs.org/configuration-options/#input
input: Object.fromEntries(
glob
.sync('src/**/*.{js,ts,vue}', {
ignore: {
ignored: p => /\.spec.(js|ts)$/.test(p.name),
},
})
.map(file => [
relative('src', file.slice(0, file.length - extname(file).length)),
fileURLToPath(new URL(file, import.meta.url)),
])
),
output: {
assetFileNames: '[name][extname]',
entryFileNames: '[name].mjs',
},
external: [...external.filter(dependency => !dependency.includes('vue-demi')), 'vue'],
},
},
});
And shout out to @emosheeep for making the plugin, it works like a charm together with multiple entries option from rollup.
And shout out to @emosheeep for making the plugin, it works like a charm together with multiple entries option from rollup.
Thanks so much,I still remember the day in last year when I was developing on my vue component library with multi entries in vite. I was driven into a corner, so I had to dive into the source code and found something useful. It's really a simple plugin that only contains 100 lines, I'm glad to see it helping so many guys🎉🎉🎉.
Clear and concise description of the problem
When buliding a lib, css will be extracted in a single file
style.css
, is there a way to bundle css in output js.Suggested solution
Like
rollup-plugin-postcss
can set extractAlternative
No response
Additional context
No response
Validations