Electron + Vite project cannot show png resource - vue.js

I am using Vite + Electron to make a desktop app demo.
But it cannot load png resource, but js, css resource is fine. So it worked like this
png canoot be loaded
when I check the console, it shows: Failed to load resource: net::ERR_FILE_NOT_FOUND
Also, the url of the png is weird:
it is not even a common file path
So what happened really ???
Here is my code:
vite.config.js
import { defineConfig } from 'vite'
import vue from '#vitejs/plugin-vue'
import path from 'path'
export default defineConfig({
base: path.resolve(__dirname, './dist/'),
plugins: [vue()]
})
index.js
const { app, BrowserWindow } = require('electron')
const path = require('path')
function createWindow () {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
webSecurity: false,
}
})
win.loadFile('dist/index.html')
win.webContents.openDevTools()
}
app.whenReady().then(() => {
createWindow()
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})
})
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
App.vue
<script setup>
// This starter template is using Vue 3 <script setup> SFCs
// Check out https://vuejs.org/api/sfc-script-setup.html#script-setup
import HelloWorld from './components/HelloWorld.vue'
</script>
<template>
<img alt="Vue logo" src="/src/assets/logo.png" />
<HelloWorld msg="Hello Vue 3 + Vite" />
</template>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
I know perhaps this problem sounds silly, but I just start it and Vue,JS... are really not my comfort zone. So if anyone could help me, I will really appreciate it.

Related

How to fix default marker-icon.png not found in vue 2 leaflet app?

I have a simple, sample project at https://github.com/ericg-vue-questions/leaflet-test/tree/feature/simple-marker
(note the feature/simple-marker branch)
The relevant code is in the LeafletTest.vue file
<template>
<div id="container">
<div id="mapContainer"></div>
</div>
</template>
<script>
import 'leaflet/dist/leaflet.css';
import L from 'leaflet';
import Vue from 'vue';
export default {
name: 'Map',
methods: {
async setupLeafletMap() {
const center = [37, -122];
const mapDiv = L.map('mapContainer').setView(center, 13);
var tiles = new L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors',
minZoom: 3,
maxZoom: 8
}).addTo(mapDiv);
L.marker(center).addTo(mapDiv);
}
},
async mounted() {
await Vue.nextTick();
await this.setupLeafletMap();
}
};
</script>
<style scoped>
#mapContainer {
width: 500px;
height: 500px;
}
</style>
When the code run, the default marker shows up as:
The URL in the img tag that L.marker(center).addTo(mapDiv); adds to the map is
<img src="marker-icon.png" class="leaflet-marker-icon leaflet-zoom-animated leaflet-interactive" alt="Marker" tabindex="0" role="button" style="margin-left: -12px; margin-top: -41px; width: 25px; height: 41px; transform: translate3d(250px, 250px, 0px); z-index: 250;">
I figure there is something extra I need to do in configuring the vue app so it and leaflet can work together in this case.
What do I need to change so the default marker-icon.png will show up by default?
One answer I found was to modify the mounted() method to be:
async mounted() {
delete L.Icon.Default.prototype._getIconUrl;
L.Icon.Default.mergeOptions({
iconRetinaUrl: require('leaflet/dist/images/marker-icon-2x.png'),
iconUrl: require('leaflet/dist/images/marker-icon.png'),
shadowUrl: require('leaflet/dist/images/marker-shadow.png')
});
await Vue.nextTick();
await this.setupLeafletMap();
}
The part that was added was:
delete L.Icon.Default.prototype._getIconUrl;
L.Icon.Default.mergeOptions({
iconRetinaUrl: require('leaflet/dist/images/marker-icon-2x.png'),
iconUrl: require('leaflet/dist/images/marker-icon.png'),
shadowUrl: require('leaflet/dist/images/marker-shadow.png')
});
If I understand correctly what is going on here is that webpack will see the require's and assist in making sure the right thing happens. If anyone has a more detailed explanation of why this works, I would be interested.

Router View keep displaying the component information even after moving onto other component

I am learning VueJS by creating a practice APP and I am stuck at a point where inside the Authors component I have a List of Authors. I want to be able to click on the list item and navigate to the AuthorDetail component, so far everything is okay. The problem arises when I use the navbar at the top to move to other view like Home or About the AuthorDetail component stays visible (it should go away!).
Code inside App.vue
<template>
<div id="nav">
<router-link to="/">Home</router-link> |
<router-link to="/authors">Authors</router-link> |
<router-link to="/about">About</router-link>
</div>
<router-view />
</template>
<style lang="scss">
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
max-width: 480px;
margin: auto;
border: 1px solid #2c3e50;
border-radius: 5px;
padding: 20px;
}
#nav {
padding: 10px;
border-bottom: 1px solid #e2e2e2;
margin-bottom: 30px;
a {
font-weight: bold;
color: #2c3e50;
&.router-link-exact-active {
color: #42b983;
}
}
}
</style>
Code in router/index.js
import { createRouter, createWebHistory } from "vue-router";
import Home from "../views/Home.vue";
import Authors from "../views/Authors.vue";
import AuthorDetail from "../views/AuthorDetail.vue";
const routes = [
{
path: "/",
name: "Home",
component: Home,
},
{
path: "/authors",
name: 'Authors',
component: Authors
},
{
path: "/authors/:id",
name: "AuthorDetail",
component: AuthorDetail
},
{
path: "/about",
name: "About",
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () =>
import(/* webpackChunkName: "about" */ "../views/About.vue"),
},
];
const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes,
});
export default router;
Code inside the Authors component.
<template>
<div>
<h1>Authors</h1>
<p>Most Popular Authors (TheTestRequest API)</p>
<div class="authors-list" :key="author.id" v-for="author in authors">
<router-link :to="{ name: 'AuthorDetail', params: { id: author.id}}">
<AuthorCard #click="showAuthor(author.id)" :author="author"></AuthorCard>
</router-link>
</div>
</div>
</template>
<script>
import AuthorCard from '#/components/AuthorCard'
export default {
name: "Authors",
components: {
AuthorCard
},
data(){
return {
authors: []
}
},
methods: {
async fetchAuthors(){
const res = await fetch('https://thetestrequest.com/authors')
const data = await res.json()
return data
},
showAuthor(authorId){
console.log("Author Clicked", authorId);
}
},
async created() {
this.authors = await this.fetchAuthors()
},
}
</script>
<style lang="scss" scoped>
.authors-list {
margin-top: 2em;
// transition: box-shadow .3s;
a {
text-decoration: none;
color: black;
}
}
</style>
Note: I am using thetestrequest.com to fetch data for this practice app.
UI Samples:
Turns out there was an error in the console which helped me resolve the issue.
Error:
AuthorDetail.vue?0959:6 Uncaught (in promise) TypeError: Cannot read property 'avatar' of null
at Proxy.eval (AuthorDetail.vue?0959:6)
at renderComponentRoot (runtime-core.esm-bundler.js?5c40:1168)
at componentEffect (runtime-core.esm-bundler.js?5c40:5214)
at reactiveEffect (reactivity.esm-bundler.js?a1e9:42)
at effect (reactivity.esm-bundler.js?a1e9:17)
at setupRenderEffect (runtime-core.esm-bundler.js?5c40:5167)
at mountComponent (runtime-core.esm-bundler.js?5c40:5126)
at processComponent (runtime-core.esm-bundler.js?5c40:5084)
at patch (runtime-core.esm-bundler.js?5c40:4690)
at componentEffect (runtime-core.esm-bundler.js?5c40:5287)
So a simple check v-if="avatar" inside AuthorDetail template did the trick for me.

Can't access functions from package installed with npm

I'm trying to access the different methods from tinyMCE, but it can't find get, setContent or insertContent. Anyone got any ideas how I can access these? The following code is a copy from their documentation.
Here is my code so far:
App.vue:
<template>
<div id="app">
<Editor id="test"></Editor>
<button #click="insertData">Test</button>
</div>
</template>
<script>
export default {
name: 'App',
components: {
Editor
},
methods: {
insertData: function () {
Editor.get("test").setContent("This is a test.")
}
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
main.js
import Vue from 'vue'
import App from './App.vue'
Vue.config.productionTip = false;
// es modulesc
var commonjsrequire = require('commonjs-require');
// NOTE: default needed after require
var Editor = require('#tinymce/tinymce-vue').default;
Vue.component('Editor',
() => import('#tinymce/tinymce-vue')
);
new Vue({
render: function (h) { return h(App) },
}).$mount('#app')
The functions you are after are tied to the tinymce global object. While you define an Editor component in the context of the application the actual API calls for TinyMCE are part of the tinymce global object.
For example:
tinymce.get("test").setContent("<p>This is a test.</p>")

Amplify Vue Chatbot not setting up

I'm trying to use the Amplify Chatbot Component in my application but I keep getting:
Chatbot - Bot not provided.
I've used the Amplify CLI to add Interactions, which added the correct configuration into the aws-exports.js file. I then set the Amplify.Configure to use the exports file.
But when I try to use the component in my app, I can't seem to get it to run.
App.vue
<template>
<amplify-chatbot ></amplify-chatbot>
</template>
<script>
import { Interactions } from 'aws-amplify';
export default {
name: 'App',
components: {
Interactions
},
data(){
return {
}
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
AWS-Exports
// WARNING: DO NOT EDIT. This file is automatically generated by AWS Amplify. It will be overwritten.
const awsmobile = {
"aws_project_region": "eu-west-1",
"aws_cognito_identity_pool_id": "eu-west-1:fbc545c0-ddac-410b-8f8d-4ba3cffadbb2",
"aws_cognito_region": "eu-west-1",
"oauth": {},
"aws_bots": "enable",
"aws_bots_config": [
{
"name": "ScheduleAppointment_dev",
"alias": "$LATEST",
"region": "eu-west-1"
}
]
};
export default awsmobile;
main.js
import Vue from 'vue'
import App from './App.vue'
import './registerServiceWorker'
import Amplify, * as AmplifyModules from 'aws-amplify'
import { AmplifyPlugin } from 'aws-amplify-vue'
import awsconfig from './aws-exports'
Amplify.configure(awsconfig)
Vue.use(AmplifyPlugin, AmplifyModules)
Vue.config.productionTip = false
new Vue({
render: h => h(App),
}).$mount('#app')
Here's a modified version of your app.vue and that will work:
<template>
<amplify-chatbot v-bind:chatbotConfig="chatbotConfig"></amplify-chatbot>
</template>
<script>
import { Interactions } from 'aws-amplify';
export default {
name: 'App',
data: () => ({
chatbotConfig:{
bot: "addTheBotNameHere",
clearComplete: true
},
}),
mounted() {
Interactions.onComplete("addTheBotNameHere", this.handleComplete);
},
methods: {
handleComplete(err,confirmation) {
if(err) {
alert("bot conversation failed");
return;
}
return "Thank You";
},
},
};
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>

VueJS + Nuxtjs Unexpected Token 'export'

So i have this code as my index page and It was working, but a couple minutes later it just stopped.
the error is:
SyntaxError
Unexpected token export
Within the script section, If i remove my import then the error will go away, but I need to import it and use it. It was working with the package being imported, but I have looked this code up and down I have no idea what the heck is going on.
Anyone have any suggestions? Am I dumb and have missed something so simple?
<template>
<section class='container'>
<img class='my-4' src="~/assets/images/carousel/1.png" alt="card" />
<div class='text-center mx-auto my-4'>
<button> Send a card </button>
<p class='subtle my-4'> Or </p>
<button class='btn-blue'> Open a card </button>
</div>
<div id="qrcode"></div>
</section>
</template>
<script>
import qrcode from 'qrcode-generator-es6'; <<<<<<<<< SYNTAX ERROR AROUND HERE
export default{
data : function(){
return {};
},
methods : {
},
mounted : function(){
const qr = new qrcode(0, 'M');
qr.addData('https://app.voxicard.com/?v=vx-9FEFCA66-F592-4FF5-97B8-93B2FD78666D');
qr.make();
document.getElementById('qrcode').innerHTML = qr.createSvgTag({
margin : 0,
cellColor : function(){
return "#48658B";
},
});
},
};
</script>
<style>
#qrcode {
width: 200px;
height: 200px;
background-color: red;
}
img {
display: block;
max-height: 500px;
text-align: center;
margin: auto;
}
button {
font-size: 125%;
}
</style>
In your build property in nuxt.config.js you'll need to add a transpile block that targets this library:
build: {
transpile: [
'qrcode-generator-es6'
]
}
This is due to the fact that nuxt expects libraries to export as CJS modules and not ES6 modules.
In nuxt.config.js replace export default { on module.exports = {