defining global variables with vite development - vue.js

Now I am using vite build tool for my vue SFC app. I read the documentation of vite with the link below:
vite config link
If I am not wrong, the define option in config could be used for defining global constants. What I want to do is to define for example the name of my App in a variable inside this option and then use it in my Vue components. But unfortunately there is no example of code in the documentation about this option.
I tried this code in my vite.config.js file:
import { defineConfig } from 'vite'
import vue from '#vitejs/plugin-vue'
// https://vitejs.dev/config/
export default defineConfig({
define: {
global: {
appName: "my-custom-name"
}
},
plugins: [vue()]
})
I am not sure that the syntax and code is correct! And also if it is correct I don't know how to call (use) this constant in my vue app components (.vue files). For example I want to use it in template or script part of this component:
<template>
<div class="bgNow">
<p class="color1">
{{ use here }}
</p>
</template>
<script>
export default {
data() {
return {
name: use here
};
},
methods: {
nameMethod() {
console.log(use here);
}
} // end of method
} // end of export
</script>
<style scoped></style>
I declared the places that want with "use here" in the code. And also if there is any other way that I could define some global constants and variables in my vite vue app, I very much appreciate your help to tell me about that.

define is a config that tells Vite how to perform a search-and-replace. It can only replace one string for another (objects cannot be used as a replacement).
For example, to replace all instances of appName with "my-custom-name", use the following config. Note JSON.stringify() is used (per the recommendation in the docs) to ensure the literal string replacement is properly quoted.
export default defineConfig({
define: {
appName: JSON.stringify('my-custom-name')
}
})
If App.vue contained:
<script setup>
console.log('appName', appName)
</script>
It would be transformed to:
<script setup>
console.log("appName", "my-custom-name")
</script>
demo

Related

Vue 3 Understanding examples from setup function and applying them in Setup tag

I am new to vue but scince i am fresh starting i decied to go straight up to TS and Setup tag because seems like the newest and best way to write vue js components.
Anyways i am now looking at this framework and more specific i'm into this example:
import { IonPage, onIonViewWillEnter, onIonViewDidEnter, onIonViewWillLeave, onIonViewDidLeave } from '#ionic/vue';
import { defineComponent } from 'vue';
export default defineComponent({
name: 'Home',
components: {
IonPage,
},
setup() {
onIonViewDidEnter(() => {
console.log('Home page did enter');
});
... the other hooks ...
},
});
And my question come from this block:
name: 'Home',
components: {
IonPage,
},
since i only worked with options api and setup tag i an not sure What does it imply to put an object in the components object and how could i acomplish the same objective with setup tag.
My objective is to make sure i am doing what this Note in the guide warns me about:
Note Pages in your app need to be using the IonPage component in order
for lifecycle methods and hooks to fire properly.
In <script setup> syntax, Home.vue would look like this:
<script setup lang="ts">
import { IonPage, onIonViewDidEnter, ...other hooks used here... } from '#ionic/vue';
onIonViewDidEnter(() => {
console.log('Home page did enter');
});
...other hooks used here...
</script>
The note you quoted draws attention to the template of any page/view contents needing to be wrapped in a <ion-page></ion-page> wrapper for the layout to function as intended, like in their examples.
Generic example:
<template>
<ion-page>
<ion-header>
<ion-toolbar>
<ion-title>Some title</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
some content...
</ion-content>
</ion-page>
</template>
For the above layout, you'd need to import all used components:
import { IonPage, IonHeader, IonToolbar, IonTitle, IonContent } from '#ionic/vue'
With <script setup> you don't need to declare them as local components, <script setup> detects them and does it for you, behind the scenes. They're available for usage inside the <template> once imported.
The component name is also inferred by <script setup> from the name of the file. In the above case, it would be Home.
To sum up: behind the scenes, <script setup> takes its contents and wraps it in a
export default defineComponent({
name: // infer from file name,
components: {
// list all imported vue components
},
setup() {
// actual contents of `<script setup>`
}
})
For this to be possible, some helpers were added (defineEmits, defineProps), which allow declaring those parts of Options API inside the setup() function.
Most notably, in this syntax setup() no longer needs a return value. All variables declared or imported inside it are made available to <template>.
Important: <script setup> is a useful tool, designed to reduce boilerplate in the majority of cases, not to replace defineComponent() completely. Read more about it in the docs.

Create "literal" component in SFC won't work?

I'm trying to create a dead simple "literal" component(MyComponent in this example) inside a SFC(vue 3):
<template>
<MyComponent>aha</MyComponent>
</template>
<script>
import { ref } from "vue";
const MyComponent = {
name: "MyCompoent",
template: "<h1>aha</h1>",
};
export default {
components: {
MyComponent,
},
};
</script>
But this won't work...
However, if I split the MyComponent into another SFC, it will work.
Anyone knows why and how to fix this?
The template option is ignored because the runtime compiler is disabled by default as an optimization. Using that option would cause a console warning like this:
[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".
In Vue CLI generated projects, set the runtimeCompiler flag to enable the template option:
// vue.config.js
module.exports = {
runtimeCompiler: true
}

Import npm package into a Vue.js Single File component

I would like to use Jodit in a SFC, but I am not sure how this is supposed to be done. I realized there is a wrapper (jodit-vue), but for educational purposes, I would like to know how it's done without it. I created a Vue CLI project with default presets, and all I changed is the App.vue:
<template>
<div id="app">
<textarea id="editor" name="editor"></textarea>
</div>
</template>
<script>
import "../node_modules/jodit/build/jodit.min.js"
export default {
name: 'App',
created(){
let editor = new Jodit('#editor');
editor.value = '<p>start</p>';
}
}
</script>
<style>
#import "../node_modules/jodit/build/jodit.min.css" ;
</style>
This produces the error: error 'Jodit' is not defined no-undef, and
if I change the import to:
import Jodit from "../node_modules/jodit/build/jodit.min.js"
Then the compilation is fine, but the browser console says:
vue.runtime.esm.js?2b0e:1888 TypeError: _node_modules_jodit_build_jodit_min_js__WEBPACK_IMPORTED_MODULE_0___default.a is not a constructor
Admittedly, I am new to all of this, but pointing me to the right direction is appreciated.
The jodit module exports the Jodit constructor, so your component would import it like this:
import { Jodit } from 'jodit'
You'd also need the Jodit styles, which could be imported like this:
import 'jodit/build/jodit.min.css'
To create a Jodit instance, we need to provide an element or selector to an existing <textarea>. The Vue component's elements are available in the mounted() lifecycle hook (not in the created() hook), so that's where we would initialize:
export default {
mounted() {
const editor = new Jodit('#editor')
editor.value = '<p>start</p>'
},
}
demo

What is the purpose of Vue.use() while importing a plugin? If we have already used vue.use , is it required to add it to the components

I'm using the plugin vue-flag-icon - https://www.npmjs.com/package/vue-flag-icon for flags, In their documentation I saw the following steps for initialising.
import FlagIcon from 'vue-flag-icon'
Vue.use(FlagIcon);
Do I need to have this? This is not specified in their docs!
export default {
components: {
FlagIcon. /// do i need to give it here ?
},
}
What is the purpose of this Vue.use(...), It's working fine even if I remove that. Can somebody help me out?
Checked the vue documentation - https://v2.vuejs.org/v2/guide/plugins.html.
Did not get a clear idea about it
Vue.use automatically prevents you from using the same plugin more than once, so calling it multiple times on the same plugin will install the plugin only once.
For the flag component, it declares a global component that you can refer within your components, such that in the following example will render correctly.
in vue-flag-icon source code
install: function (Vue) {
if (VuePlugin.installed) {
return;
}
VuePlugin.installed = true;
Vue.component('flag', Flag);
}
You can see that with Vue.component('flag', Flag) that this is a root level component declaration, therefore, in your components, you do not require to declare something like following
Unnecessary if using Vue.use
import { Flag } from "vue-flag-icon"
export default {
components: { Flag }
}
If Vue.use is not used, the flag tag in the template will throw an error if you do not include it as a component within your vue init.
<template>
<div id="app">
<img src="./assets/logo.png">
<flag iso="it" />
<flag iso="gb" />
<flag iso="us" />
</div>
</template>
<script>
export default {
name: 'app',
}
</script>

How to Access Vue-Loader Components in an HTML File

I would like to use the modular style and file format of Vue Loader (i.e., where I have a template section, script section and style section in each .vue file).
What I can't figure out how to do (or if it is even possible to do) is use my custom templates in an html file.
For instance, in the App.vue file I can use the following code:
<template>
<div id="app">
<message>Hello there</message>
</div>
</template>
This will work to display a custom message component on the home page.
What I would like to do instead is use my custom components in html files. For instance, in the index.html file to use the following code:
<div id="app">
<message>Hello there</message>
</div>
Any idea how I can do this? Thanks.
NOTE: I am new to Vue Loader and semi-new to Vue (so I apologize in advance if the answer to this question is obvious).
There are many ways you can compile a single file component and then use that component in a web page.
Use vue-cli
Vue released a command line interface tool called vue-cli that can initialize projects and build components with zero configuration. One option to build a component that you can use in your page is to use vue build.
vue build MyComponent.vue --prod --lib MyComponent
This will compile a script that exposes MyComponent. If you include that script in your page and then add it globally,
Vue.component(MyComponent)
That component will be available to you in any of your Vues.
Make a plugin
Here is a sample of a very basic framework for making a plugin.
myPluginDefinition.js
window.MyPlugin= {};
MyPlugin.install = function (Vue) {
Vue.component('my-component', require('./my-component.vue'));
}
webpack.config.js
module.exports = {
entry: "./myPluginDefinition.js",
output: {
path: __dirname+'/dist',
filename: "MyPlugin.js"
},
module: {
loaders: [
{
test: /\.vue$/,
loader: 'vue-loader',
}
]
}
};
This will build a file called MyPlugin.js that will contain each of the single file components that you include in the install function. Include the script on your page and then call
Vue.use(MyPlugin)
and you will have all of your components.
Use a custom webpack configuration
There are many ways you could configure webpack to build your single file components. You could build them all into a single file or build them separately. I suggest if you want to use one of these options you ask a separate question.
Actually you can do this easily by:
register your component :
Vue.component('message', {
template: '<div>A custom component!</div>'
});
then comment the render function in your Vue instance like so:
new Vue({
el: '#app',
// render: h => h(App)
})
after that you will be able to render your message Tag like this:
<div id="app">
<message></message>
</div>
Edit :
if you don't want to use this way you can define it in your view instance:
new Vue({
el: '#app',
// render: h => h(App)
components: {
message: {
template: `
<h1>Hello World</h1>
`
}
}
})
Import desired component definition object and pass it to options.components
<template>
<some-component></some-component>
</template>
<style>...</style>
<script>
import SomeComponent from 'path/to/some-component.vue';
export default {
components: {
// ES2015 shorthand for SomeComponent: SomeComponent
SomeComponent
}
}
</script>
That leverages local component registration
Both the default export and SomeComponent are component definition objects.