As title, my styles (including style tag in SFC and css imported to app.ts) are missing when I compile my app in IIFE format.
I have no idea whether it's by Vite or RollUp... It works properly with vite serve, but not vite build.
I saw the css emitted in other format, but not IIFE. For that, I can't load Vue form CDN, which I want to.
// vite.config.js
import vue from "#vitejs/plugin-vue";
import { defineConfig } from "vite";
import env from "vite-plugin-env-compatible";
export default defineConfig({
plugins: [
env({
prefix: "",
mountedPath: "process.env",
}),
vue(),
],
build: {
minify: true,
rollupOptions: {
external: ["vue"],
output: {
format: "iife",
globals: {
vue: "Vue",
},
},
},
},
});
// src/app.ts
import { createApp } from "vue";
import App from "./App.vue";
import "./main.css";
createApp(App).mount("#app");
<!-- src/App.vue -->
<template>
<h1>Hello World</h1>
<button #click="increment">Click Me!</button>
<div>Clicked: {{ count }}</div>
</template>
<script setup lang="ts">
import { ref } from "vue";
//#region Counter
const count = ref(0);
const increment = () => (count.value += 1);
//#endregion
</script>
<style scoped>
h1 {
color: green;
}
</style>
I found in documentation, all I need is setting build.cssCodeSplit to false.
https://vitejs.dev/guide/features.html#css-code-splitting
Related issue for follow up
Related
I am creating a library that wraps Vuetify 3 components. But when I try to use the library it gives the following error:
[Vue warn]: Failed to resolve component: v-btn If this is a native custom element, make sure to exclude it from component resolution via compilerOptions.isCustomElement.
Library vite.config.ts :
import { fileURLToPath, URL } from 'node:url';
import { resolve } from 'node:path';
import { defineConfig } from 'vite';
import vue from '#vitejs/plugin-vue';
import vueJsx from '#vitejs/plugin-vue-jsx';
import vuetify from 'vite-plugin-vuetify';
export default defineConfig({
plugins: [
vue(),
vueJsx(),
// vuetify({ autoImport: true, styles: 'none' }), // Don't export vuetify
],
resolve: {
alias: {
'#': fileURLToPath(new URL('./src', import.meta.url)),
},
},
build: {
lib: {
entry: resolve(__dirname, 'src/main.ts'),
name: '#my/ui',
// the proper extensions will be added
fileName: 'my-ui',
},
rollupOptions: {
// make sure to externalize deps that shouldn't be bundled
// into your library
external: ['vue', 'vuetify'],
output: {
// Provide global variables to use in the UMD build
// for externalized deps
globals: {
vue: 'Vue',
vuetify: 'Vuetify',
},
},
},
},
});
Nuxt project nuxt.config.ts:
import { defineNuxtConfig } from 'nuxt';
import vuetify from 'vite-plugin-vuetify';
export default defineNuxtConfig({
css: ['#/assets/css/main.css'],
modules: [
async (options, nuxt) => {
nuxt.hooks.hook('vite:extendConfig', (config) =>
config.plugins.push(vuetify({ autoImport: true }))
);
},
],
build: {
transpile: ['#my/ui', 'vuetify'],
},
});
Nuxt project app.vue:
<template>
<v-app>
<v-main>
<HelloWorld label="Test" primary />
</v-main>
</v-app>
</template>
<script lang="ts" setup>
import { HelloWorld } from '#my/ui';
</script>
Nuxt project plugin vuetify.ts:
import 'vuetify/styles';
import { createVuetify } from 'vuetify';
import * as components from 'vuetify/components';
import * as directives from 'vuetify/directives';
export default defineNuxtPlugin((nuxtApp) => {
const vuetify = createVuetify({
// components, if imported components getting resolved but treeshaking doesn't work.
// directives
});
nuxtApp.vueApp.use(vuetify);
});
Expected Behavior
Vuetify components from the Library project should be auto imported.
Current workaround:
If the vuetify components are imported in the parent project then the components are resolved. But this causes issue as the library users has to know what to import or import on global which is creating larger bundle size.
Is there an alternative way to implement and meet the following criteria:
Wrapping module doesn't depend on vuetify (Peer dep only)
Consuming app can auto import and get all of the benefits of tree shaking
Consuming app doesn't need to import any of the peer dependencies of the wrapping module.
Thank you so much in advance.
Just to create an answer for the workaround Sasank described:
If you just want to get rid of the error, import the components into the parent project as described in this link: https://next.vuetifyjs.com/en/features/treeshaking/#manual-imports
I have tried to use the Bpmn.io modeler plus panel properties in Vue3 and I followed exactly what they have described in this example in Bpmn.io official examples. But it seems doesn't work properly in Vue (I guess Vuejs is the reason), and I don't know why. I can see the custom group but inside it is completely empty.
These are my codes:
main.js
import { createApp } from 'vue'
import App from './App.vue'
import '../node_modules/bpmn-js/dist/assets/bpmn-js.css'
import '../node_modules/bpmn-js/dist/assets/diagram-js.css'
import '../node_modules/bpmn-js/dist/assets/diagram-js.css'
import '../node_modules/bpmn-js/dist/assets/bpmn-font/css/bpmn-embedded.css'
import '../node_modules/bpmn-js-properties-panel/dist/assets/properties-panel.css'
createApp(App).mount('#app')
App.vue
<template>
<div>
<div id="js-canvas"></div>
<div id="js-properties-panel"></div>
</div>
</template>
<script>
import BpmnModeler from "bpmn-js/lib/Modeler";
import {
BpmnPropertiesPanelModule,
BpmnPropertiesProviderModule,
} from "bpmn-js-properties-panel";
import magicPropertiesProviderModule from "./provider/magic/";
import magicModdleDescriptor from "./descriptors/magic";
export default {
mounted() {
const diagram = `
<?xml version="1.0" encoding="UTF-8"?>
<bpmn2:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd" id="sample-diagram" targetNamespace="http://bpmn.io/schema/bpmn">
<bpmn2:process id="Process_1" isExecutable="false">
<bpmn2:startEvent id="StartEvent_1"/>
</bpmn2:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1">
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
<dc:Bounds height="36.0" width="36.0" x="412.0" y="240.0"/>
</bpmndi:BPMNShape>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn2:definitions>
`;
const bpmnModeler = new BpmnModeler({
container: "#js-canvas",
propertiesPanel: {
parent: "#js-properties-panel",
},
additionalModules: [
BpmnPropertiesPanelModule,
BpmnPropertiesProviderModule,
magicPropertiesProviderModule,
],
moddleExtensions: {
magic: magicModdleDescriptor,
},
});
bpmnModeler.importXML(diagram);
},
};
</script>
I solved my problem
I found out that I need to configure your compiler to recognize JSX properly.
That's the solution:
1- Adding "#babel/plugin-transform-react-jsx": "^7.18.6" as a devDependency in package.json
2- Adding plugins config to the babel.config.js
module.exports = {
presets: [
'#vue/cli-plugin-babel/preset'
],
plugins: [
[
'#babel/plugin-transform-react-jsx',
{
throwIfNamespace: false,
runtime: 'automatic',
importSource: '#bpmn-io/properties-panel/preact',
}
]
]
}
i'm new to vue js an wanted to write a fancy little demo.
I was trying to use tailwindcss in a new project.
I've created the project with
vue create vue-tailwind-template
and added tailwind with
vue add tailwind
I removed the demo component "helloworld" an all styles. In App.vue i try to use an div with class "bg-red", but no red background in output. These are my project files. Does anybody see the problem? Thank you in advance.
Sven
postcss.config.js
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {}
}
}
tailwind.config.js
module.exports = {
purge: [],
darkMode: false, // or 'media' or 'class'
theme: {
extend: {},
},
variants: {
extend: {},
},
plugins: [],
}
App.vue
<template>
<img alt="Vue logo" src="./assets/logo.png">
<div class="bg-red"><p>Hallo</p></div>
</template>
<script>
export default {
name: 'App',
components: {
}
}
</script>
<style>
</style>
main.js
import { createApp } from 'vue'
import App from './App.vue'
import './assets/tailwind.css'
createApp(App).mount('#app')
Problem solved.
Classname "bg-red" doesn't exist. I had to use a number to define color intensity, e.g. "bg-red-500"
I use vue3 with composition api, but when I build my project, the ref element always undefined.
I reproduced it, maybe I used it incorrectly, but I don't know why.
I defined a ref in hooks function.
const isShow = ref(false)
const rootRef = ref<HTMLDivElement>();
export default function () {
function changeShow() {
isShow.value = !isShow.value;
console.log(isShow.value, rootRef.value);
}
return { isShow, rootRef, changeShow };
}
Use rootRef in the HelloWorld.vue and linked element.
<script setup lang="ts">
import useShow from "../composables/useShow";
const { rootRef, isShow } = useShow();
</script>
<template>
<div ref="rootRef" v-show="isShow" class="test"></div>
</template>
Create a button in App.vue and bind click function.
<script setup lang="ts">
import HelloWorld from "./components/HelloWorld.vue";
import useShow from "./composables/useShow";
const { changeShow } = useShow();
</script>
<template>
<button #click="changeShow">切换</button>
<HelloWorld />
</template>
When I click button, it works.
But when I build it and import from lib, it doesn't work.
My vite.config.ts is as follows:
export default defineConfig({
plugins: [vue()],
resolve: {
alias: {
"#": path.resolve(__dirname, "src")
}
},
build: {
cssCodeSplit: true,
sourcemap: true,
lib: {
entry: path.resolve(__dirname, "src/index.ts"),
name: "my-project",
fileName: format => `my-project.${format}.js`
},
rollupOptions: {
external: ["vue"],
preserveEntrySignatures: "strict",
output: {
globals: {
vue: "Vue"
}
}
}
}
});
I think the problem is the definition of rootRef. It seems that only binding location can use it. This is no different from defining it in a component. I need to use it in multiple places.
Oddly, in this way, the Dev environment works fine, but Pro env is not available. Do I need to modify the build configuration of vite.
How do I do that?
The problem is your App.vue uses its own copy of composables/useShow instead of the one from the lib.
The solution is to export the composable from the lib so that your app can use the same one:
// src/index.ts
import { default as useShow } from './composables/useShow';
//...
export default {
//...
useShow
};
In App.vue, use the lib's composable:
import MyProject from "../dist/my-project.es";
const { changeShow } = MyProject.useShow();
GitHub PR
I created two plugins in my VueJS app powered by Vue CLI 4 but when I tried to use it in my page only one will be working
| plugins
|-- axios.vue
|-- authentication.vue
axios.vue
import Vue from "vue";
Plugin.install = function(Vue) {
Vue.prototype.$myName = "Dean Armada";
};
Vue.use(Plugin);
export default Plugin;
authentication.vue
import Vue from "vue";
Plugin.install = function(Vue) {
Vue.prototype.$name = "Chris Guinto";
};
Vue.use(Plugin);
export default Plugin;
main.js
import axios from "./plugins/axios.js";
import authentication from "./plugins/authentication.js";
Vue.use(axios);
Vue.use(authentication);
instructions.vue
<template>
<div>
Hello World
</div>
</template>
<script>
export default {
created() {
console.log(this.$name);
console.log(this.$myName);
}
}
</script>
<style lang="scss" scoped>
</style>
TAKE NOTE
The output above will be "Dean Armada" only and the console.log(this.$name) is undefined
But if I commented out the Vue.use(axios) the console.log(this.$name) will work so the output will be "Chris Guinto" and the other one is undefined because the axios plugin is not activated
So how can I make them both work at the same time?
Perhaps try and simplify it a little with the following approach?
// plugins/axios.js
export default {
install(Vue){
Vue.prototype.$myname = "Dean Armada";
}
}
// plugins/authentication.js
export default {
install(Vue){
Vue.prototype.$name = "Chris Guinto";
}
}
// main.js
import axios from "./plugins/axios.js";
import authentication from "./plugins/authentication.js";
Vue.use(axios);
Vue.use(authentication);
new Vue({
el: '#app',
render: h => h(App)
})