SvelteKit console error "window is not defined" when i import library - import

I would like to import apexChart library which using "window" property, and i get error in console.
[vite] Error when evaluating SSR module /src/routes/prehled.svelte:
ReferenceError: window is not defined
I tried use a apexCharts after mount, but the error did not disappear.
<script>
import ApexCharts from 'apexcharts'
import { onMount } from 'svelte'
const myOptions = {...myOptions}
onMount(() => {
const chart = new ApexCharts(document.querySelector('[data-chart="profit"]'), myOptions)
chart.render()
})
</script>
I tried import a apexCharts when i am sure that browser exist.
import { browser } from '$app/env'
if (browser) {
import ApexCharts from 'apexcharts'
}
But i got error "'import' and 'export' may only appear at the top level"
I tried disable ssr in svelte.config.js
import adapter from '#sveltejs/adapter-static';
const config = {
kit: {
adapter: adapter(),
prerender: {
enabled: false
},
ssr: false,
}
I tried to create a component in which I import apexChart library and I created a condition that uses this component only if a browser exists
{ #if browser }
<ProfitChart />
{ /if }
Nothing helped.
Does anyone know how to help me please?

The easiest way is to simply include apexcharts like a standalone library in your webpage like this:
<script src="https://cdn.jsdelivr.net/npm/apexcharts"></script>
And then simply use it in the onMount:
onMount(() => {
const chart = new ApexCharts(container, options)
chart.render()
})
You can add this line either in your app.html or include it where it's required with a <svelte:head> block.
An alternative way would be to dynamically import during onMount:
onMount(async () => {
const ApexCharts = (await import('apexcharts')).default
const chart = new ApexCharts(container, options)
chart.render()
})
As an extra: use bind:this instead of document.querySelector to get DOM elements, that would be the more 'svelte' way.

I have found the last option with the Vite plugin to work best with less code in the end but will lose intellisense in vscode and see import highlighted as error (temp workaround at end): https://kit.svelte.dev/faq#how-do-i-use-x-with-sveltekit-how-do-i-use-a-client-side-only-library-that-depends-on-document-or-window
Install vite plugin: npm i -D vite-plugin-iso-import
Add plugin to svelte.config.js:
kit: {
vite: {
plugins: [
isoImport(),
],
Add plugin to TypeScript config (if you use TS):
"compilerOptions": {
"plugins": [{ "name": "vite-plugin-iso-import" }],
Use as normal but note the "?client" on the import:
<script context="module">
import { chart } from 'svelte-apexcharts?client';
import { onMount } from 'svelte'
let myOptions = {...myOptions}
onMount(() => {
myOptions = {...updated options/data}
});
</script>
<div use:chart={myOptions} />
Debugging note:
To have import not highlighting as an error temporarily, just:
npm run dev, your project will compile fine, then test in browser to execute at least once.
remove ?client now, save and continue debugging as usual.

For all of you trying to import dynamically into a js or ts file, try the following:
Import your package during on mount in any svelte component.
onMount(async () => {
const Example = await import('#creator/examplePackage');
usePackageInJSOrTS(Example.default);
});
Use the imported package in your js/ts function. You need to pass the default value of the constructor.
export function usePackageInJsOrTs(NeededPackage) {
let neededPacakge = new NeededPackage();
}

Related

Nuxt vuex - moving store from Vue

I have been fiddling with moving a tutorial I did in Vue to Nuxt. I have been able to get everything working, however I feel I'm not doing it the "proper way". I have added the Nuxt axios module, but wasnt able to get it working, so I ended up just using the usual axios npm module. Here is my store:
import Vue from 'vue'
import Vuex from 'vuex'
import axios from 'axios'
import VueAxios from 'vue-axios'
Vue.use(Vuex)
Vue.use(VueAxios, axios)
export const state = () => ({
events: []
})
export const mutations = {
setEvents: (state, events) => {
state.events = events
}
}
export const actions = {
loadEvents: async context => {
let uri = 'http://localhost:4000/events';
const response = await axios.get(uri)
context.commit('setEvents', response.data)
}
}
I would like to know how to re-write this store using the #nuxtjs/axios module. I also didnt think I'd need to import vuex here, but if I dont, my app doesn't work.
Thanks for any help!
Using the #nuxtjs/axios module, you can configure axios inside your nuxt.config.js:
// nuxt.config.js
export default {
modules: [
'#nuxtjs/axios',
],
axios: {
// proxy: true
}
}
You can use it inside your store (or components) with this.$axios
// In store
{
actions: {
async getIP ({ commit }) {
const ip = await this.$axios.$get('http://icanhazip.com')
commit('SET_IP', ip)
}
}
}

Javascript in nuxt plugins folder - how to use in component?

I have a javascript variable (var testButton) in my Nuxt plugins folder. I then added the file to my nuxt.config.js plugins. In my component, I have a Buefy button, and I'm trying to call the script:
<b-button #click="testButton">Click Me</b-button>
...
<script>
export default {
mounted () {
this.$testButton()
}
}
</script>
I import the script in my script section and have tried computed and mounted lifecycles. Not sure what I'm doing wrong. Thank you
Check the following things, you must be missing one or more:
1. Your plugin should export a method. That method should receive an 'inject' function and use it to register your 'testButton' function.
So, in your ~/plugins/testButton.js
export default (context, inject) => {
inject('testButton', () => {
console.log('testButton works!')
})
}
2. You shuold register your plugin correctly in the nuxt.conf.js file
Do it like so:
plugins: [
{ src: '~/plugins/testButton.js' },
],
3. Call it as '$testButton()' (note that Nuxt will have added a dollar sign to your method's name).
Your '$testButton' method will now be available from anywhere in your nuxt app. You don't have to import it o create any computed property.
<b-button #click="$testButton">Click Me</b-button>
<script>
export default {
}
</script>

Can't import tween using import

I have an es6 script that include a tween library with es6 import. The code works fine if it's not transpiled, I mean I can import tween and use it inside the script, if I use webpacke with my configuration the script exit with an error becouse the TWEEN is somehow undefined.
I have tried change extension of tween file with mjs but it generate other errors like
require is not defined
I webpack add core-js modules using require funcition
require("core-js/modules/es.symbol");
The code with issue
'use strict';
...
import {TWEEN} from '../threejs/tween.js';
//import {TWEEN} from '../threejs/tween.js';
...
export class CustomClass extends ParentClass {
constructor(arguments) {
super(arguments);
this.tweenGroup = new TWEEN.Group(); // the line that generate "Cant get Group of undefined"
}
...
}
...
this is my babel-loader configuration configuration
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
sourceType: 'module'
}
}
},
my babel configuration is look like this
module.exports = {
presets: [
[
'#babel/preset-env',
{
debug: true,
useBuiltIns: 'usage',
corejs: 3
}
]
],
plugins: [
// '#babel/plugin-proposal-class-properties',
// '#babel/plugin-transform-runtime',
// '#babel/runtime-corejs2',
// '#babel/plugin-syntax-dynamic-import',
// '#babel/plugin-syntax-async-generators',
// '#babel/plugin-transform-regenerator',
// '#babel/plugin-transform-async-to-generator',
'#babel/plugin-transform-modules-commonjs',
// '#babel/plugin-transform-typeof-symbol'
]
};
The code with TWEEN import (the first block of code I posted) work just fine if I use it in a project that is not transpiled with babel, but it generate the error if I run devserver. I don't understand why I can't import the Tween properly afetr compilation.
I will apriciate any help.l
Update: I realized I had rather different setup and different issue than you did, but while searching the solution I found this thread with recommendation for npm intalling tween for babel workflow. Maybe that is helpful for you.
I still leave my initial reply here, could be useful for anyone else:
I had some trouble including TWEEN within my js project (eg using import * as TWEEN from '...'), but following the those steps for simple installation I got it working after I included it in HTML, not in js:
<script src="js/libs/Tween.js"></script>

share a method of use axios globally standard for nuxtjs?

i want use it for all components and pages and my config present :
~/plugins/axios
import axios from 'axios'
export default axios.create({
baseURL: 'http://127.0.0.1:3001/'
})
but with this way , i must import axios from '~/plugins/axios' in components and pages
i want use something choise for like this :
this.$axios.post('url',data).then(res=>{
// do something in here
}).catch({
// do something in here
})
and no need import more axios
I recommend you to use the official "Axios Module" for Nuxt.js: https://github.com/nuxt-community/axios-module
npm install #nuxtjs/axios
First, you can set your baseURL in the nuxt.config.js or in an env variable (see https://axios.nuxtjs.org/options):
modules: [
'#nuxtjs/axios'
],
axios: {
baseURL: 'http://127.0.0.1:3001/' // or, Environment variable API_URL_BROWSER can be used to override browserBaseURL.
}
Then in <page>.vue, no more import, axios is injected in the app var (see https://axios.nuxtjs.org/usage):
<script>
export default {
asyncData ({ app }) {
app.$axios.$get(`/api/users`).then(
// do something in here
);
//...
}
}
</script>
Finally, you can handle errors globally with a custom plugin (see https://axios.nuxtjs.org/extend)
$axios.onError(error => {
// do something in here
})

aurelia/skeleton-plugin cant run test on custum element

i have created an aurelia plugin using the skelton-plugin https://github.com/aurelia/skeleton-plugin i am now looking at writing unit tests for it.
i am stuggling to get a unit test running for a custom element ive added to the project. i started with the 'testing a custom element' example from http://aurelia.io/hub.html#/doc/article/aurelia/testing/latest/testing-components/3
template:
<template>
<div class="firstName">${firstName}</div>
</template>
vm
import {bindable} from 'aurelia-framework';
export class MyComponent {
#bindable firstName;
}
i added this to the src folder.
my test code is
import {StageComponent} from 'aurelia-testing';
import {bootstrap} from 'aurelia-bootstrapper';
describe('MyComponent', () => {
let component;
beforeEach(() => {
component = StageComponent
.withResources('my-component')
.inView('<my-component first-name.bind="firstName"></my-component>')
.boundTo({ firstName: 'Bob' });
});
it('should render first name', done => {
component.create(bootstrap).then(() => {
const nameElement = document.querySelector('.firstName');
expect(nameElement.innerHTML).toBe('Bob');
done();
}).catch(e => { console.log(e.toString()) });
});
afterEach(() => {
component.dispose();
});
});
i jspm installed aurelia-bootstrapper and aurelia-testing to get it running.
im now getting the error
Error{stack: '(SystemJS) XHR error (404 Not Found) loading http://localhost:9876/base/my-component.js
so it looks like karma cant find my component. i checked the karma.config file and the jspm loadFiles: ['test/setup.js', 'test/unit/**/*.js'], looks correct.
has any one run into a similar issue?
solved the issue.
in karma.config.js file needed to change
serveFiles: ['src//.']
to
serveFiles: ['src//*.js', 'src/**/*.html']