I'm trying to get a Vue project setup with runtime compilation, but I'm not quite sure how to configure this in Snowpack.
Basically currently when I run the project I get a blank screen and the usual "[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".
Currently my files look like below:
snowpack.config.js:
/** #type {import("snowpack").SnowpackUserConfig } */
module.exports = {
mount: {
public: '/',
src: '/_dist_',
},
plugins: [
'#snowpack/plugin-vue',
'#snowpack/plugin-dotenv'
],
...
}
index.js:
import { createApp } from "vue";
// import App from "./App.vue";
import First from "./First.vue";
// const app = createApp(App);
const app = createApp({
data() {
return {
message: 'duck',
}
}
});
app.component('first', First);
app.component('ducks', {
props: ['todo'],
template: '<li>{{ todo }}</li>'
});
app.mount("#app");
// Hot Module Replacement (HMR) - Remove this snippet to remove HMR.
// Learn more: https://www.snowpack.dev/#hot-module-replacement
if (import.meta.hot) {
import.meta.hot.accept();
import.meta.hot.dispose(() => {
app.unmount();
});
}
index.html:
...
<body>
<div id="app">
<p>stuff should be fine:</p>
<p>{{message}}</p>
<ul>
<li>hello</li>
<ducks todo="testing"></ducks>
<ducks todo="goats"></ducks>
<ducks todo="canoes"></ducks>
</ul>
</div>
<noscript>You need to enable JavaScript to run this app.</noscript>
<script type="module" src="/_dist_/index.js"></script>
</body>
...
I've tried adding an alias but that doesn't seem to do anything:
snowpack.config.js
module.exports = {
...
plugins: [
'#snowpack/plugin-vue',
'#snowpack/plugin-dotenv'
]
...
alias: {
'vue': 'vue/dist/vue.esm-bundler.js'
}
Anybody know how I can get runtime compilation setup?
Thanks,
Matt
I managed to fix this, by using import { createApp, h } from "vue/dist/vue.cjs.prod.js";.
But I'm not sure if this will create other issues in the future.
I'm trying to use TipTap with Nuxt but can't seem to figure out why it won't work. I've read issues on the repo and used their suggestions but I just get these errors:
ERROR in /Volumes/Projects/nuxt/candy-hub-lerna/node_modules/prosemirror-state/dist/index.mjs
Can't import the named export 'ReplaceStep' from non EcmaScript module (only default export is available)
ERROR in /Volumes/Projects/nuxt/candy-hub-lerna/node_modules/prosemirror-view/dist/index.mjs
Can't import the named export 'Selection' from non EcmaScript module (only default export is available)
ERROR in /Volumes/Projects/nuxt/candy-hub-lerna/node_modules/prosemirror-transform/dist/index.mjs
Can't import the named export 'Slice' from non EcmaScript module (only default export is available)
Set up
My set up is pretty simple and echoes this github issue
/components/forms/RichText.vue
<template>
<no-ssr>
<editor-content :editor="editor" />
</no-ssr>
</template>
<script>
import { Editor, EditorContent } from 'tiptap'
export default {
components: {
EditorContent
},
data () {
return {
editor: null
}
},
mounted () {
this.editor = new Editor({
content: '<p>This is just a boring paragraph</p>'
})
},
beforeDestroy () {
// Always destroy your editor instance when it's no longer needed
this.editor.destroy()
}
}
</script>
/components/global/LocalisedAttributes.vue
<template>
<div>
<rich-text />
</div>
</template>
<script>
import RichText from '~/components/forms/RichText.vue'
export default {
components: {
RichText
}
}
</script>
I've tried adding 'prosemirror-view' and 'tiptap' to build.transpile array in nuxt.config.js but it hasn't had any effect.
If anyones got it working on Nuxt I'd be grateful for any insight in to their set up.
Looks like it was an issue with Lerna, I've switched to yarn workspaces and now things seem to be working!
I added plugin: vue-burger-menu to my nuxt.js project. And i have an error: "document is not defined". I know, that this plugin is available only for client-side. So I found in vue documentation enter link description here what I have to do to fix it. It works only for first refresh. Then I have again document is not defined.
nuxt.config.js:
build: {
vendor: ['vue-burger-menu'],
}
plugins: [
{ src: '~/plugins/vue-burger-menu.js', ssr: false }
],
Add a file to my plugins folder called "vue-burger-menu.js":
import Vue from 'vue';
import VueBurgerMenu from 'vue-burger-menu';
if (process.browser) {
Vue.use(VueBurgerMenu);
}
nav template
<template lang="pug">
Slide(right)
nav.menu_vertical
</template>
<script>
import { Slide } from 'vue-burger-menu'
export default {
name: 'Nav',
components: {
Slide
},
}
Replace deprecated process.browser with process.client
if (process.client) {
Vue.use(VueBurgerMenu);
}
Nuxt is doing SSR and document is only available in browser so you need to wrap your plugin code like
change "vue-burger-menu.js" as following
import Vue from 'vue';
import VueBurgerMenu from 'vue-burger-menu';
if (process.browser) {
Vue.use(VueBurgerMenu);
}
you can find detail documentation Here
I'm trying to install Vue Typer in my Nuxt js app but no luck. I keep getting "document not defined". I tried importing it in my nuxt.config.js as a plugin but it doesn't work.
I got it working in my VueCLI 3, seems to work fine with this method.
Appreciate it!
Getting
NuxtServerError render function or template not defined in component: anonymous
////plugins///
import Vue from vue;
if (process.client) {
const VueTyper = require('vue-typer');
Vue.use(VueTyper);
}
///nuxt.config.js///
plugins: [
{src: '~/plugins/vue-typer.js', ssr: false}
],
<template>
<vue-typer text='Hello World! I was registered locally!'></vue-typer>
</template>
<script>
const VueTyper = processs.client ? require('vue-typer'): '';
export default {
components: {
VueTyper
}
}
</script>
To fix this, create a file called vueTyper.client.js under plugin folder then type this;
import Vue from 'vue';
import { VueTyper } from 'vue-typer';
Vue.component('vue-typer', VueTyper);
then in your nuxt.config.js add this to your plugin
plugins: [
{src: '~/plugins/vueTyper.client.js', mode: 'client',}
]
after doing this you can easily use it anywhere in your application without error:
<vue-typer text='Hello World! I was registered locally!'></vue-typer>
In vue single file component.I import a svg file like this:
import A from 'a.svg'
And then how can I use A in my component?
Based on the information you provided, what you can do is:
Install vue-svg-loader
npm install --save-dev vue-svg-loader
Configure webpack:
module: {
rules: [
{
test: /\.svg$/,
loader: 'vue-svg-loader', // `vue-svg` for webpack 1.x
},
],
},
Import the svg and use it as a regular component:
<template>
<nav id="menu">
<a href="...">
<SomeIcon class="icon" />
Some page
</a>
</nav>
</template>
<script>
import SomeIcon from './assets/some-icon.svg';
export default {
name: 'menu',
components: {
SomeIcon,
},
};
</script>
Reference: https://github.com/visualfanatic/vue-svg-loader
I've gotten the following to work in Vue 3. Doesn't require messing with webpack or installing any third party plugins.
<template>
<img :src="mySVG" />
</template>
<script>
export default {
name: 'App',
data(){
return {
mySVG: require('./assets/my-svg-file.svg')
}
}
}
</script>
Note: I'm aware that you cannot modify certain pieces of the SVG when using it in img src, but if you simply want to use SVG files like you would any other image, this seems to be a quick and easy solution.
If you have control over the svg file, you can just wrap it in a vue file like so:
a.vue:
<template>
<svg>...</svg>
</template>
Just require the file like this afterwards: import A from 'a.vue'
If you are using Webpack you can use the require context to load SVG files from a directory. Be aware that this will put all SVG files within your Javascript files and might bloat your code though.
As a simplified example I am using this svg component:
data() {
return {
svg: ''
};
},
props: {
name: {
type: String,
required: true
}
}
created() {
this.svg = require(`resources/assets/images/svg/${this.name}.svg`);
}
The template simply looks like this:
<template>
<div :class="classes" v-html="svg"></div>
</template>
Normally you can't simply load SVG files like that and expect them to be used with a v-html directive since you are not getting the raw output. You have to use the Webpack raw-loader so make sure you get the raw output:
{
test: /\.svg$/,
use: [
{
loader: 'raw-loader',
query: {
name: 'images/svg/[name].[ext]'
}
},
{
loader: 'svgo-loader',
options: svgoConfig
}
]
}
The example above also uses the svgo-loader since you will want to heavily optimize your SVG files if you do down this route.
Hopefully this help you or anyone else out on how to solve this without diving straight into a third-party solution to fix this.
I would just use vue-svg
Install via Vue CLI 3:
vue add svg
Input:
<img src="#/assets/logo.svg?data" />
Output:
<img src="data:image/svg+xml;base64,..." />
or this is work also...
import LogoImage from "#/assets/logo.svg?inline"
You can also use something like this:
<template>
<img :src="logo"></img>
</template>
<script>
import logo from '../assets/img/logo.svg'
export default {
data() {
return {
logo
}
}
}
</script>
This doesn't require installing external modules and works out of the box.
I like to use pug as a template engine (comes with many advantages) - if you do so, you will be able to easily include files like SVG's just by writing:
include ../assets/some-icon.svg
That's it! there is nothing else to do - I think this is an very easy and convenient way to include stuff like smaller svg's - file's easily included code is still clean!
Here you can get some more information how to include PugJS into you Vue instance https://www.npmjs.com/package/vue-cli-plugin-pug
First you need a specific loader for the component which will contain the svg
my webpack.base.config.js
module: {
rules: [
{
test: /\.svg$/,
loader: 'vue-svg-loader',
},
{
test: /\.vue$/,
use: [
{
loader: "vue-loader",
options: vueLoaderConfig
},
{
loader: "vue-svg-inline-loader",
options: { /* ... */ }
}
]
}
//.. your other rules
}
docs of vues-svg-inline-loader : https://www.npmjs.com/package/vue-svg-inline-loader
docs of vue-svg-loader : https://www.npmjs.com/package/vue-svg-loader
Next, you can initialise a vue file
<template>
<div>
<img svg-inline class="icon" src='../pathtoyourfile/yoursvgfile.svg' alt="example" />
</div>
</template>
<script>
import axios from 'axios'
export default {
name: 'logo',
data () {
},
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
#logo{
width:20%;
}
.rounded-card{
border-radius:15px;
}
//the style of your svg
//look for it in your svg file ..
//example
.cls-1,.cls-7{isolation:isolate;}.cls-2{fill:url(#linear-gradient);}.cls-3{fill:url(#linear-gradient-2);};stroke-width:2px;}..cls-6{opacity:0.75;mix-blend-mode:multiply;}.cls-7{opacity:0.13;}.cls-8{fill:#ed6a29;}.cls-9{fill:#e2522b;}.cls-10{fill:#ed956e;}.cls-185{fill:#ffc933;}..cls-13{fill:#ffd56e;}.cls-14{fill:#1db4d8;}.cls-15{fill:#0f9fb7;}.cls-16{fill:#3ad4ed;}.cls-17{fill:#25bdde;}.cls-18{fill:#fff;}
//
</style>
Your svg fils must dont contain style tag so copy paste the style in the vue style with scoped propoerty to keep it specific to this component
you can just load you component in specific place of your app
and use it
<template>
<v-app id="app">
<logo/>
<router-view/>
</v-app>
</template>
<script>
import logo from './components/logo.vue'
export default {
name: 'App',
data(){
return {
//your data
}
},
components:{
logo //the name of the component you imported
},
}
}
</script>
<style>
#app {
font-family: 'Hellow', sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #070b0f;
margin-top: 60px;
}
</style>
You can always save it as a .svg file in your /static/svg/myfile.svg (using webpack) and just use it as an image file: <img src="/static/svg/myfile.svg">. No require / import / loader needed.
+1 for #Stephan-v's solution, but here's a slightly modified approach for 2021 with Webpack 5.
Your Vue component <template/>
Option A: Single SVG file
<template>
<svg viewBox="0 0 24 24">
<use :xlink:href="require('#/assets/icons/icon.svg')"></use>
</svg>
</template>
Option B: SVG Sprite (e.g. for FeatherIcons)
<template>
<svg viewBox="0 0 24 24">
<use
:xlink:href="require('#/assets/icons/sprite.svg') + `#${iconName}`"
></use>
</svg>
</template>
<script>
export default {
props: {
// Dynamic property to easily switch out the SVG which will be used
iconName: {
type: String,
default: "star",
},
},
};
</script>
You may need a Webpack loader.
NOTE: You may not need the Webpack Loader if you're using Vue 3 (as mentioned above) or Vite. If you're using Storybook or Nuxt, you will likely still need it.
$ npm install svgo-loader -D
$ yarn add svgo-loader -D
webpack.config.js (or similar)
module.exports = {
mode: "development",
entry: "./foo.js",
output: {},
// ... other config ...
module: {
rules: [
/////////////
{
// Webpack 5 SVG loader
// https://webpack.js.org/guides/asset-modules/
// https://dev.to/smelukov/webpack-5-asset-modules-2o3h
test: /\.svg$/,
type: "asset",
use: "svgo-loader",
},
],
/////////////
},
};
Done!
I was able to get svgs loading inline via
<div v-html="svgStringHere"></div>
Where svgStringHere is a computed property that returns an svg as a string