Tailwindcss / Vite / Vue - Using #{!important} - results in [vite] Internal server error: [postcss] Unknown word or with '!w-3' [vite] expected ";" - vuejs3

dev dependencies
{
"vue": "^3.2.45",
"vite": "^4.0.3",
"sass": "^1.57.1",
"postcss": "^8.4.19",
"tailwindcss": "^3.2.4",
}
Vite.config.ts
import { defineConfig, type PluginOption } from 'vite'
import vue from '#vitejs/plugin-vue'
import eslintPlugin from 'vite-plugin-eslint'
import { visualizer } from 'rollup-plugin-visualizer'
import type { UserConfig as VitestUserConfigInterface } from "vitest/config"
import dts from 'vite-plugin-dts'
import { resolve } from 'path'
const vitestConfig: VitestUserConfigInterface = {
test: {
globals: true,
environment: "jsdom",
},
}
export default defineConfig({
build: {
target: ['edge90', 'chrome90', 'firefox90', 'safari15'],
outDir: './dist',
lib: {
formats: ['es', 'cjs'],
entry: resolve(__dirname, './src/components/index.ts'),
name: 'Vuesty',
fileName: 'index',
},
rollupOptions: {
external: ['vue'],
output: { globals: { vue: 'Vue' } },
},
},
test: vitestConfig.test,
plugins: [vue(), eslintPlugin(),
dts({
beforeWriteFile: (filePath, content) => {
const newFilePath = filePath
.replace('/src', '/global');
return {
filePath: newFilePath,
content,
};
},
skipDiagnostics: true,
}),
visualizer({
emitFile: true
}) as PluginOption
],
})
avatar.scss
.v-avatar__status-circle_large{
#apply !w-2.5 ;
}
Avatar.vue
<style lang="scss">
#import "src/assets/themes/main/components/avatar.scss";
</style>
If i use global styles, not importing it directly into component then it works fine, but i need it exactly in the component
If the code is:
.v-avatar__status-circle_large{
#apply !w-2.5 ;
}
Then error is: [vite] Internal server error: [sass] expected ";".
And if the code is:
.v-avatar__status-circle_large{
#apply w-2.5 #{!important};
}
Error:[vite] Internal server error The important class does not exist. If important is a custom class, make sure it is defined within a #layer directive.

Related

Vite import generetad chunks in index.js with url

in my Vue3 project I import the components in the router index.js like that:
{
path: settingsStore.startUri,
name: "home",
component: () => import("../views/Home/Home.vue"),
},
My vite.config looks like that:
import { defineConfig } from "vite";
import vue from "#vitejs/plugin-vue";
import vuetify from "vite-plugin-vuetify";
const path = require("path");
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
// https://github.com/vuetifyjs/vuetify-loader/tree/next/packages/vite-plugin
vuetify({
autoImport: true,
}),
],
define: {
"process.env": {},
__VUE_I18N_FULL_INSTALL__: true,
__VUE_I18N_LEGACY_API__: false,
__INTLIFY_PROD_DEVTOOLS__: false,
},
resolve: {
alias: {
"#": path.resolve(__dirname, "src"),
},
},
build: {
rollupOptions: {
output: {
entryFileNames: "news-[name].js",
assetFileNames: "news-[name].[ext]",
manualChunks: undefined,
chunkFileNames: "chunks/[name].js",
},
},
},
optimizeDeps: {
include: ["vue", "axios"],
},
});
When I run npm run build it creates a chunk directory with some smaller .js files beeing imported in the index.js but as relativ paths like that:
import("./chunks/Home.js")
But I need to import the files from an url like that:
import("https://example.com/chunks/Home.js")
Does anyone know if thats possible and how can I do that?
I tried a lot, read a lot of documentations but didnt find an answer

Use scoped CSS in Vue components from library (no data tags)

When building a reusable Vue component library, the scoped CSS is not applied, because the PostCSS data-tags are missing. (If the component is not imported as a package, but directly imported into the project it works as intended: styles are applied, and data-tags are present, so the SFC itself is okay.)
https://vuejs.org/api/sfc-css-features.html
I'm building the components use Vite, so maybe it's something to configure in vite.config.ts?
vite.config.ts
import { fileURLToPath, URL } from 'node:url'
import { defineConfig, type PluginOption } from 'vite'
import vue from '#vitejs/plugin-vue'
import vuetify from 'vite-plugin-vuetify'
import typeScript2 from "rollup-plugin-typescript2"
import { visualizer } from "rollup-plugin-visualizer"
export default defineConfig({
plugins: [
vue(),
vuetify(),
typeScript2({
check: false,
include: ["src/components/*.vue"],
tsconfigOverride: {
compilerOptions: {
sourceMap: true,
declaration: true,
declarationMap: true,
}
},
exclude: [
"vite.config.ts"
]
}),
visualizer() as PluginOption
],
resolve: {
alias: {
'#': fileURLToPath(new URL('./src', import.meta.url))
}
},
build: {
cssCodeSplit: false,
lib: {
entry: './src/components/index.ts',
formats: ["es", "cjs"],
name: "CommonVtfyPlugin",
fileName: format => (format == "es" ? "index.js" : "index.cjs"),
},
rollupOptions: {
external: ["vue", "vuetify", "vuetify/lib", 'vuetify/lib/util/colors.mjs'],
output: {
exports: 'named',
globals: {
vue: "Vue",
vuetify: "Vuetify",
'vuetify/components': "VuetifyComponents",
'vuetify/directives': "VuetifyDirectives",
'vuetify/lib/util/colors.mjs': 'colors'
}
}
}
}
})
The Single File Component:
<template>
<v-select
:class="{'nkd':isNkd}"
....
>
....
</v-select>
</template>
<style scoped>
.nkd :deep(.v-field__input) {
padding: 0;
min-height: auto;
}
.nkd :deep(.v-field) {
padding: 0;
align-items: center;
background-color: transparent;
}
.nkd :deep(.v-field__append-inner) {
padding: 0;
}
</style>
I don't think it matters, but the SFC component uses a Vuetify component (V-Select).

Include 3rd party scss in component library using Vue 3 + Vite

I'm currently building an external component library using Vue 3 + Vite. I'm using 3rd party component and style, but the style doesn't apply when I used it in my main project. It used to work before when I use Vue 2 + Vue CLI.
My component library project looks like this:
and here's the detail for my code
vite.config.js
import { resolve } from 'path'
import { defineConfig } from 'vite'
import vue from '#vitejs/plugin-vue'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
build: {
lib: {
entry: resolve(__dirname, 'src/main.js'),
name: 'custom-lib',
fileName: 'custom-lib',
},
rollupOptions: {
external: ['vue'],
output: {
globals: {
vue: 'Vue'
}
}
}
}
})
package.json
{
"name": "custom-lib",
"private": true,
"version": "0.0.0",
"type": "module",
"files": [
"dist"
],
"main": "./dist/custom-lib.umd.cjs",
"module": "./dist/custom-lib.js",
"exports": {
".": {
"import": "./dist/custom-lib.js",
"require": "./dist/custom-lib.umd.cjs"
}
},
"scripts": {
"build": "vite build"
},
"dependencies": {
"moment": "^2.29.4",
"vue": "^3.2.41",
"vue-datepicker-next": "^1.0.2"
},
"devDependencies": {
"#vitejs/plugin-vue": "^3.2.0",
"sass": "^1.56.0",
"sass-loader": "^13.1.0",
"vite": "^3.2.3"
}
}
src/components/Datepicker.vue
<template>
<DatePicker
:id="id"
v-model:value="inputVal"
value-type="date"
type="date"
:format="dateFormat"
:placeholder="dateFormat"
:disabled="disabled"
input-class="mx-input"
/>
</template>
<script>
import DatePicker from 'vue-datepicker-next';
import moment from 'moment';
export default {
name: 'Datepicker',
components: {
DatePicker
},
props: {
id: {
type: String,
required: true
},
modelValue: null,
dateFormat: String,
disabled: Boolean
},
computed: {
inputVal: {
get() {
if (this.modelValue) {
return moment(this.modelValue).toDate();
}
return null;
},
set(val) {
let strVal = undefined;
let m = moment(val);
if (m.isValid()) {
strVal = m.format("YYYY-MM-DDTHH:mm:ss");
}
this.$emit('update:modelValue', strVal);
}
}
}
};
</script>
<style lang="scss">
#import "vue-datepicker-next/scss/index.scss";
</style>
src/main.js
import Datepicker from './components/Datepicker.vue';
export {
Datepicker
}
My Datepicker style not working in my main project, is there something missing from the config?
As I was suggesting in comment, you can use vite-plugin-css-injected-by-js
Add the plugin to your component project:
npm i vite-plugin-css-injected-by-js --save
Add the plugin to vite config of your custom component:
import { resolve } from 'path'
import { defineConfig } from 'vite'
import vue from '#vitejs/plugin-vue'
import cssInjectedByJsPlugin from 'vite-plugin-css-injected-by-js' // 👈
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
cssInjectedByJsPlugin() // 👈
],
build: {
lib: {
entry: resolve(__dirname, 'src/main.js'),
name: 'custom-lib',
fileName: 'custom-lib',
},
rollupOptions: {
external: ['vue'],
output: {
globals: {
vue: 'Vue'
}
}
}
}
})
It should work without hassle.
See it on Stackblitz:
you can go in test folder (cd test) and run yarn dev to launch the preview.
preview:
https://stackblitz.com/edit/vitejs-vite-yd1rzw
Result:

Using Dynamic Vue Component in VitePress

I am starting a vue 3 component library which uses a component with a dynamic template.
The dynamic template requires the use of vue/dist/vue.esm-bundler.js. The vue 3 component compiles using vite as long as the following alias fpr
"vue" is included in the vite.config.ts file:
export default defineConfig({
plugins: [vue()],
define: {
global: {},
},
resolve: {
alias: {
"#": fileURLToPath(new URL("./src", import.meta.url)),
'vue': 'vue/dist/vue.esm-bundler.js',
'./runtimeConfig': './runtimeConfig.browser',
},
},
});
However, the same component is used in the vitepress documentation for this library and does not compile. I have added the same alias to the vitepress configuration file:
const path = require('path')
module.exports = {
title: '',
description: '',
themeConfig: {
repo: '',
sidebar: [
{
text: 'Introduction',
items: [
{ text: 'What is My Lib?', link: '/' },
],
}, {
text: 'Components',
items: [
{ text: 'B-Markdown', link: '/components/b-markdown/desc' },
],
}
],
},
vite: {
resolve: {
alias: {
'vue': 'vue/dist/vue.esm-bundler.js'
}
},
}
}
I also tried switching the alias to use
'vue': path.resolve(__dirname, '../../node_modules/vue/dist/vue.esm-bundler.js'),
When compiling the vitepress documentation using either of these vue alias lines, I obtain the following error:
runtime-core.esm-bundler.js:38 [Vue warn]: Component provided template option but runtime compilation is not supported in this build of Vue. Configure your bundler to alias "vue" to "vue/dist/vue.esm-bundler.js".
at <Anonymous content="Test content." imgFolder="" class="toastui-editor-contents" ... >
at <VRuntimeTemplate class="toastui-editor-contents" style= {max-width: '900px', margin: 'auto'} template="<div><p>Test content.</p>\n</div>" >
at <BMarkdown content="Test content." >
at <Basic>
at <DemoContainer>
at <Components/bMarkdown/desc.md>
at <VitePressContent class="vp-doc _components_b-markdown_desc" >
at <VPDoc key=3 >
at <VPContent>
at <Layout>
at <VitePressApp>
Is this a problem with vitepress not registering the alias?

Cannot read properties of undefined (reading 'scoped')

I'm building an UI Library based on rollup.
An error occurred and I have no idea how to solve it.
TypeError: Cannot read properties of undefined (reading 'scoped')
at transformStyle (C:\my-kit\node_modules\#vitejs\plugin-vue\dist\index.js:4597:19)
at Object.transform (C:\my-kit\node_modules\#vitejs\plugin-vue\dist\index.js:4747:18)
at C:\my-kit\node_modules\rollup\dist\shared\rollup.js:22870:37 {
code: 'PLUGIN_ERROR',
plugin: 'commonjs--resolver',
hook: 'resolveId',
id: 'C:\\my-kit\\packages\\my-ui\\icon\\select-icon-svg.vue?vue&type=style&index=0&scoped=true&lang.less',
it looks like something wrong with parsing vue.
const block = descriptor.styles[index];
the value of block is undefined, error occurred when accessing the scoped property of block.
this is my rollup config. Hope there's someone who can help me.
import { rollup } from "rollup";
import { nodeResolve } from "#rollup/plugin-node-resolve";
import fastGlob from "fast-glob";
import vue from "#vitejs/plugin-vue";
import vueJsx from "#vitejs/plugin-vue-jsx";
import css from "rollup-plugin-css-only";
import commonjs from "#rollup/plugin-commonjs";
import esbuild from "rollup-plugin-esbuild";
import postcss from "rollup-plugin-postcss";
import postcssImport from "postcss-import";
import { babel, getBabelOutputPlugin } from "#rollup/plugin-babel";
import defineOptions from "unplugin-vue-define-options/rollup";
import { UI_PATH } from "./path";
import { resolve } from "path";
import pkgJson from "../packages/my-ui/package.json";
export const buildEsm = async () => {
const input = await fastGlob("**/*.{js,ts,jsx,tsx,vue}", {
cwd: UI_PATH,
absolute: true,
onlyFiles: true,
ignore: ["node_modules"],
});
try {
const bundle = await rollup({
input,
plugins: [
css(),
postcss({
extensions: [".css", ".less", ".scss"],
modules: true,
extract: true,
use: {
sass: null,
stylus: null,
less: { javascriptEnabled: true },
},
plugins: [postcssImport()],
}),
defineOptions(),
vue({
isProduction: false,
}),
vueJsx(),
nodeResolve({
extensions: [".js", ".json", ".ts", ".jsx", ".tsx", ".vue"],
}),
commonjs(),
esbuild({
sourceMap: true,
target: "es2018",
loaders: {
".vue": "ts",
},
}),
getBabelOutputPlugin({
configFile: resolve(__dirname, "../babel.config.js"),
}),
babel({
exclude: "node_modules/**",
extensions: [".js", ".jsx", ".ts", ".tsx", ".vue"],
babelHelpers: "bundled",
}),
],
external: Object.keys(pkgJson.peerDependencies),
});
// write the bundle to disk
await bundle.write({
format: "esm",
dir: resolve(UI_PATH, "es"),
});
} catch (err) {
console.error(err);
}
};

Resources