vue-i18n not substituting tokens in production build - vuejs2

We have a Quasar 2 based project that makes use of vue-i18n for localising of strings, but are running into an issue whereby strings with replacement tokens aren't getting handled properly in our dev host and production deployments.
In our language file:
export default {
'label.deleteUserConfirm': 'Saisissez le {personId} pour confirmer la suppression'
}
In our Vue file, in the template section:
<template>
<div>
{{ $t('label.deleteUserConfirm', { personId: '12345' }) }}
</div>
</template>
When running in localhost the displayed text is:
Saisissez le 12345 pour confirmer la suppression
In our deployments
Saisissez le {personId} pour confirmer la suppression
Based on docs for #intlify/vite-plugin-vue-i18n we did try specifying compositionOnly: false in the quasar.conf.js, but that doesn't seem to have made a difference.
We are building our project with Vite. Looking in the dist/spa folder we don't see any evidence of corruption of the strings, as they appear in the js, in the assets folder.
The results of quasar build show this issue, while the dev version run by quasar dev don't. This is an SPA target.
Environment info:
vue-i18n 9.2.2
vite 2.9.15
#intlify/vite-plugin-vue-i18n 6.0.3
quasar 2.10.1
node 16.10.0
Update: I just tried creating a Quasar project from scratch using yarn create quasar and it shows the same issues. Trying this with new vue + vue-i18n project, using vite, only shows the issue once I use #intlify/unplugin-vue-i18n/vite, suggesting the issue is related to that.

If you are using Vue2 use this library Vue-i18n for Vue2
If you are using vue3 use this one Vue-i18n for Vue3.
It will work fine with these packages
These packages supported by nuxt and vue community so it will best solution

Turns out we need to provide the runtimeOnly: false option, to #intlify/vite-plugin-vue-i18n, to deal with this issue.
The documentation does cover this, but it isn't clear until you run into this problem:
Also, if you do a production build with vite, Vue I18n will automatically bundle the runtime only module. If you need on-demand compilation with Message compiler, you need to set the runtimeOnly option to false.
If I understand rightly, then without this option the messages are optimised at compile time and can't benefit from the token substitutions.
So, if you are using Quasar, in the quasar.conf.js
vitePlugins: [
['#intlify/vite-plugin-vue-i18n', {
// if you want to use Vue I18n Legacy API, you
// need to set `compositionOnly: false`
// compositionOnly: false,
runtimeOnly: false,
// you need to set i18n resource including paths !
include: path.resolve(__dirname, './src/i18n/**')
}]
],
If you are using pure Vue3, with Vite, then in the vite.config.ts file:
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '#vitejs/plugin-vue'
import VueI18nPlugin from '#intlify/unplugin-vue-i18n/vite'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
VueI18nPlugin({
runtimeOnly: false
})
],
resolve: {
alias: {
'#': fileURLToPath(new URL('./src', import.meta.url))
}
}
})

Related

VUE: SFC - use markdown in <docs> tag - vite throwing eror

So I inherited an old (Vue 2) app that uses Styleguidist for creating style guide and documenting components...
It was running extra slow so my first task was to upgrade to using vite instead of webpack. Almost there... fixed almost all the issue, the one is outstanding though... this app uses this format of *.vue components
<template>...</template>
<script>...</script>
<style>...</style>
<docs>
Example of usage
```jsx
<MyComponent>...</MyComponent>
</docs>
where content inside is markdown, so one can write nicer documentation with code example
Now, vite is complaining that I am trying to use jsx (where I am not)...
this is the error
3:36:36 PM [vite] Internal server error: Failed to parse source for
import analysis because the content contains invalid JS syntax. If you
are using JSX, make sure to name the file with the .jsx or .tsx
extension. Plugin: vite:import-analysis
So what am I to do? How do I tell VITE to ignore that part?
The solution, as posted here, is to create a small Vite plugin that ignores the <docs> blocks.
Add this to vite.config.js:
const vueDocsPlugin = {
name: 'vue-docs',
transform(code, id) {
if (!/vue&type=docs/.test(id))
return;
return `export default ''`;
}
};
Then add the plugin to the plugins array:
export default defineConfig({
plugins: [
// vue() will be here...
vueDocsPlugin,
],
});

Web3js fails to import in Vue3 composition api project

I've created a brand new project with npm init vite bar -- --template vue. I've done an npm install web3 and I can see my package-lock.json includes this package. My node_modules directory also includes the web3 modules.
So then I added this line to main.js:
import { createApp } from 'vue'
import App from './App.vue'
import Web3 from 'web3' <-- This line
createApp(App).mount('#app')
And I get the following error:
I don't understand what is going on here. I'm fairly new to using npm so I'm not super sure what to Google. The errors are coming from node_modules/web3/lib/index.js, node_modules/web3-core/lib/index.js, node_modules/web3-core-requestmanager/lib/index.js, and finally node_modules/util/util.js. I suspect it has to do with one of these:
I'm using Vue 3
I'm using Vue 3 Composition API
I'm using Vue 3 Composition API SFC <script setup> tag (but I imported it in main.js so I don't think it is this one)
web3js is in Typescript and my Vue3 project is not configured for Typescript
But as I am fairly new to JavaScript and Vue and Web3 I am not sure how to focus my Googling on this error. My background is Python, Go, Terraform. Basically the back end of the back end. Front end JavaScript is new to me.
How do I go about resolving this issue?
Option 1: Polyfill Node globals/modules
Polyfilling the Node globals and modules enables the web3 import to run in the browser:
Install the ESBuild plugins that polyfill Node globals/modules:
npm i -D #esbuild-plugins/node-globals-polyfill
npm i -D #esbuild-plugins/node-modules-polyfill
Configure optimizeDeps.esbuildOptions to use these ESBuild plugins.
Configure define to replace global with globalThis (the browser equivalent).
import { defineConfig } from 'vite'
import GlobalsPolyfills from '#esbuild-plugins/node-globals-polyfill'
import NodeModulesPolyfills from '#esbuild-plugins/node-modules-polyfill'
export default defineConfig({
⋮
optimizeDeps: {
esbuildOptions: {
2️⃣
plugins: [
NodeModulesPolyfills(),
GlobalsPolyfills({
process: true,
buffer: true,
}),
],
3️⃣
define: {
global: 'globalThis',
},
},
},
})
demo 1
Note: The polyfills add considerable size to the build output.
Option 2: Use pre-bundled script
web3 distributes a bundled script at web3/dist/web3.min.js, which can run in the browser without any configuration (listed as "pure js"). You could configure a resolve.alias to pull in that file:
import { defineConfig } from 'vite'
export default defineConfig({
⋮
resolve: {
alias: {
web3: 'web3/dist/web3.min.js',
},
// or
alias: [
{
find: 'web3',
replacement: 'web3/dist/web3.min.js',
},
],
},
})
demo 2
Note: This option produces 469.4 KiB smaller output than Option 1.
You can avoid the Uncaught ReferenceError: process is not defined error by adding this in your vite config
export default defineConfig({
// ...
define: {
'process.env': process.env
}
})
I found the best solution.
The problem is because you lose window.process variable, and process exists only on node, not the browser.
So you should inject it to browser when the app loads.
Add this line to your app:
window.process = {
...window.process,
};

Vue: icons are not displayed when css.extract: false

When building a Vue library (component), according to Vue docs, you can set css.extract: false in vue.config.js to avoid the users having to import the CSS manually when they import the library into an app:
vue.config.js
module.exports = {
css: {
extract: false
}
}
However, when you do that, the icons are not displayed in the production build.
In this case I'm using #mdi/font and weather-icons. Neither of them load:
To reproduce
You can reproduce this with this Vue library (component):
Create new Vue project with vue create test
Clone the repo and put in the same directory as the Vue test project
In vue-open-weather-widget set css.extract: false in vue.config.js;
And comment out CSS import:
import 'vue-open-weather-widget/dist/vue-open-weather-widget.css'
Build vue-open-weather-widget with yarn build
Import it into the test Vue app with yarn add "../vue-open-weather-widget";
Serve the test app yarn serve
I have looked at your lib (nice component BTW). I created a build with css: { extract: false } and first looked at the behavior when importing vue-open-weather-widget.umd.js directly into an HTML file. And that worked without any problems.
The thing is that the fonts remain external in the dist after the build. And it seems that there is a problem to find the fonts when your component is loaded in a Webpack project (in our case Vue CLI project). I don't know why the fonts are not referenced correctly. But I have found another, and possibly a better solution.
As it is stated in the MDI docs, the use of the web fonts can negatively affect the page performance. When importing only one icon, all of them are imported, which in turn increases the bundle size. In such a small component this is more than suboptimal, especially for the component users. Therefore here is the alternative solution, also suggested by MDI:
Use #mdi/js instead of #mdi/font
Remove all #mdi/font references in your code and install deps:
npm install #mdi/js #jamescoyle/vue-icon
Replace all icons with SVG(e.g. in MainView.vue). Note that on this way only icons are included in the bundle that are used in your components:
...
<span #click="state.settings.view = 'settings'">
<svg-icon type="mdi" :path="mdiCogOutline"></svg-icon>
</span>
...
import SvgIcon from '#jamescoyle/vue-icon'
import { mdiCogOutline } from '#mdi/js'
...
components: {
SvgIcon
},
data () {
return {
mdiCogOutline: mdiCogOutline
}
},
Adjust vue.config.js:
module.exports = {
css: {
extract: false
}
}
Build component:
# i would also include --formats umd-min
vue-cli-service build --target lib --formats umd-min --name vue-open-weather-widget src/main.js
Now your dist contains only 192.68 KiB vue-open-weather-widget.umd.min.js and the component is ready to use over CDN or in a Vue CLI Project, without importing any CSS or fonts. I have tested both cases. Here is how it looks like:
Hope it helps you! Feel free to ask if you have further questions.

css changed after nuxt generate

I'm using Nuxt with Vuetify.
I created a class and assigned it some padding.
The class is defined in a unscoped <style> in layouts/default.vue.
when I'm on development mode (npm run dev) everything looks great as I aimed for.
the class is on container element so the final html looks like
<div class="container container--fluid my-class">
the devtools look like that when I'm on dev mode:
so my-class is applied. But once I build the project (npm run generate) my-class is overridden by the container class rules:
I guess it is happening because of the order in which the classes combined into a single css but not sure it behaves differently for dev and built projects.
How can I fix it?
After some more digging it seems to be a known issue with nuxt.
It happens when declaring styles in non-scoped style tag, and using it somewhere else.
I followed these steps: https://stackoverflow.com/a/60925793/9103301
which is basically integrating Vuetify into nuxt manually and not with #nuxt/vuetify.
then I could control over the order the css is loaded in nuxt.config.js - first vuetify and then my styling (which I moved from the layout the a css file).
a more basic vuetify plugin that worked for me:
import Vue from "vue"
import Vuetify from "vuetify"
version "^2.1.1" ,
Vue.use(Vuetify)
export default (ctx) => {
const vuetify = new Vuetify({
theme: {
dark: false, // From 2.0 You have to select the theme dark or light here
},
})
ctx.app.vuetify = vuetify
ctx.$vuetify = vuetify.framework
}
You'll have to install icons as well, vuetify default is mdi which is installed with npm install #mdi/font -D
managed to fix this by disabling tree shaking for vuetify. Change the following in nuxt.config.js:
buildModules: [
["#nuxtjs/vuetify", { treeShake: false }],
],

I want quilljs in nuxt.js (vue.js)

I know vue-quill-editor.
However, I am having difficulties.
First, I started with
vue vue-init nuxt / express myProject
and
npm install --save vue-quill-editor
~plugins/quill.js
import Vue from 'vue'
if (process.BROWSER_BUILD) {
require('quill/dist/quill.snow.css')
require('quill/dist/quill.bubble.css')
require('quill/dist/quill.core.css')
Vue.use(require('vue-quill-editor/ssr'))
}
nuxt.config.js
plugins: [
{ src: '~plugins/quill.js' }
]
Is this the right way?
How do I add modules here?
For example,
Import {ImageImport} from '../modules/ImageImport.js'
Import {ImageResize} from '../modules/ImageResize.js'
Quill.register ('modules / imageImport', ImageImport)
Quill.register ('modules / imageResize', ImageResize)
I could refer to the following,
but it does not seem to be an example of a nuxt.js environment. So I failed.
https://github.com/surmon-china/vue-quill-editor/tree/master/examples
Thank you for your help.
You should take a look this package: Vue Quill Editor. This package has example for NuxtJS in here. I've been successful with this.
The best pratice is to use the ssr: false option in plugins to run the file only on the client-side.
nuxt.config.js
module.exports = {
plugins: [
{ src: '~plugins/quill.js', ssr: false }
],
}
Check the Nuxt doc: https://nuxtjs.org/guide/plugins#client-side-only
quills is for vue2 and vue3. if you are using nuxtjs that use vue2 you have to use this enter link description here
if you are using vuejs 3 you can use this enter link description here