Vue3 + Webpack Encore styles are not applied - vue.js

I use Vue3 with webpack encore. tag in single file components are not included in build. My configuration is default. I also tried this Configuring Vue framework with webpack - styles are not applied but it didn't help in my case.
webpack.config.js
const Encore = require('#symfony/webpack-encore');
if (!Encore.isRuntimeEnvironmentConfigured()) {
Encore.configureRuntimeEnvironment(process.env.NODE_ENV || 'dev');
}
Encore
[...]
.enableVueLoader(() => {}, { runtimeCompilerBuild: true })
.configureCssLoader((config) => {
config.esModule = false; //it does not matter, didn't help
})
;
module.exports = Encore.getWebpackConfig();
main.vue
<template>
[...]
</template>
<script>
export default {
name: 'Main',
}
</script>
<style>
body{
color: green;
}
</style>

Related

Styles is missing after I bundle my project with Vite

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

Npm package Vue3 UI library don't run in Nuxt

I have a UI library with Vue3 Composition API components. It works fine in other Vue projects but there is a problem in Nuxt 2.6 project.
My library has component Badge
// components/badge.vue
<template>
<div :class="classes">{{ label }}</div>
</template>
<script>
import { computed, reactive } from 'vue';
export default {
name: 'badge',
props: {
label: {
type: String,
required: true,
},
highlighted: {
type: Boolean,
default: false,
}
},
setup(props, { emit }) {
props = reactive(props);
return {
classes: computed(() => ({
'badge': true,
'badge--highlighted': props.highlighted
})),
onClick() {
emit('click');
}
}
},
}
</script>
<style lang="scss">
#import '_variables';
.badge {
font-size: $badge-font-size;
border-radius: $badge-border-radius;
background-color: $badge-bg;
color: $badge-color;
display: inline-block;
line-height: $badge-line-height;
padding: $badge-padding;
&--highlighted {
background-color: $badge-bg-accent;
color: $badge-color-accent;
}
}
</style>
I export component for npm package
// components/index.js
export { default as Badge } from './Badge/Badge.vue';
Build npm package with Umd and Es files and publish as private package
In Nuxt project I installed package and created plugin to use it.
// plugins/CupPatternLibrary.ts
import Vue from 'vue';
import * as CupPatternLibrary from '#cambridgecore/cup-pattern-library';
Vue.use(CupPatternLibrary);
import {
Badge
} from '#cambridgecore/cup-pattern-library'
Vue.component('Badge', Badge)
Registered plugin
// nuxt.config.js
plugins: [
'~/plugins/CupPatternLibrary.ts'
],
and want to use it
// landing-page.vue
<Badge label="xxx" />
And now i get TypeError and browser display error
Cannot read properties of undefined (reading 'classes')
in file
node_modules\#cambridgecore\cup-pattern-library\dist\cup-pattern-library.umd.js:2:416
So my question is how to make npm package to work with Nuxt project

NuxtJS how to transfer colors from store json to css vars?

Im fetching colors from backend from vuex store, and i need to set that colors to css variables. And this variables need to be aviable on every page. how i can do that?
Assume you load the color settings on nuxtServerInit action in Vuex (ref), and the format is:
{
primary: '#F00',
secondary: '#000'
}
By layouts
You can bind those variables as inline styles (ref) to the root element of your layout (ref), for example, layouts/default.vue:
<template>
<div :style="styles">
<nuxt />
</div>
</template>
<script>
import { mapState } from 'vuex'
export default {
computed: {
...mapState([
'colorsFromBackend'
]),
styles () {
const obj = {}
for (const key in this.colorsFromBackend) {
obj[`--${key}`] = this.colorsFromBackend[key]
}
return obj
}
}
}
</script>
Then you can use the variables under the layout:
<template>
<div class="demo">CSS Variable Testing</div>
</template>
<style scoped>
.demo {
color: var(--primary);
background: var(--secondary);
}
</style>
Here is a live demo: https://codesandbox.io/s/css-variable-with-nuxt-js-7lp9t4
By plugins
Alternatively, if you want to use the variables globally, you can done this by inserting a style tag to <head> through a Nuxt plugin (ref), the plugin will be executed in client only before rendering Vue components (ref).
First, add the plugin configuration in nuxt.config.js:
export default {
// ...
plugins: [
{
src: '~/plugins/css-var.js',
mode: 'client' // Important for running in client side only
}
]
}
Then, add the plugin file css-var.js under plugins/ directory:
export default ({ app, store }) => {
// Fetch the color object from Vuex
const colorsFromBackend = store.state.colorsFromBackend
// Set the css content
let styleContent = ''
for (const key in colorsFromBackend) {
styleContent += `--${key}: ${colorsFromBackend[key]};`
}
// Create a style tag
const style = document.createElement('style')
style.id = 'css-var'
style.innerText = `:root{${styleContent}}`
// Append the tag to the end of `head`
document.head.appendChild(style)
}
With this approach, the css variables will be declared within :root, which points to <html> (ref), so you can access the css variables everywhere in the app.
Live demo: https://codesandbox.io/s/css-variable-with-nuxt-js-plugin-enjkri

vite 2 production env ref element is undefined with compostion api

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

Monaco Editor Web Worker Issue with Vue 3

I was trying to implement Monaco Editor in Vue 3 application but I could not get the web worker running.
// Editor.vue
<template>
<div id="container">
<div id="editor-section"></div>
<button #click="runCode">Run</button>
</div>
</template>
<script>
import * as monaco from "monaco-editor";
import { onMounted } from "vue";
export default {
name: "Editor",
setup() {
let codeEditor = null;
function initEditor() {
codeEditor = monaco.editor.create(document.getElementById("editor-section"), {
value: "function hello() {\n\talert('Hello world!');\n}",
language: "javascript",
theme: "vs-dark"
});
}
function runCode() {
console.log("runCode");
console.log(codeEditor.getValue());
}
onMounted(() => {
initEditor();
})
return { codeEditor, runCode }
},
};
</script>
I am getting the Editor but there is this issue
I am using
// vue.config.js
const MonacoWebpackPlugin = require("monaco-editor-webpack-plugin");
module.exports = {
plugins: [
new MonacoWebpackPlugin()
]
};
Am I missing anything?
Should I care about the Issue anyway?
My goal of the project is I want to implement a web editor that takes the written file and compiles in docker container.
It looks like you put the plugin in the wrong place. It's supposed to be placed in configureWebpack which represents for webpack configuration instead:
vue.config.js
const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin');
module.exports = {
configureWebpack: {
plugins: [
new MonacoWebpackPlugin(), // Place it here
]
},
// ...
}