12

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?

LukasGur
  • 311
  • 4
  • 14

3 Answers3

11

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.

AlexRMU
  • 47
  • 1
  • 6
Stephane Vanraes
  • 14,343
  • 2
  • 23
  • 41
6

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

  1. Install vite plugin: npm i -D vite-plugin-iso-import
  2. Add plugin to svelte.config.js:
       kit: {
          vite: {
            plugins: [
                isoImport(),
            ],
  1. Add plugin to TypeScript config (if you use TS):
"compilerOptions": {
    "plugins": [{ "name": "vite-plugin-iso-import" }],
  1. 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:

  1. npm run dev, your project will compile fine, then test in browser to execute at least once.
  2. remove ?client now, save and continue debugging as usual.
AEQ
  • 1,339
  • 1
  • 16
  • 20
  • 1
    Also checkout this reddit post: https://www.reddit.com/r/sveltejs/comments/n508th/comment/gx8sest/?utm_source=share&utm_medium=web2x&context=3 – AEQ Nov 10 '21 at 09:16
  • `vite-plugin-iso-import` documentation https://github.com/bluwy/vite-plugin-iso-import – Mikko Ohtamaa Jan 28 '22 at 09:50
0

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();
}