Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DOCS: How to use in SSR context #543

Closed
jerssonMA opened this issue Aug 7, 2020 · 26 comments · Fixed by #613
Closed

DOCS: How to use in SSR context #543

jerssonMA opened this issue Aug 7, 2020 · 26 comments · Fixed by #613
Labels
documentation Improvements or additions to the documentation
Milestone

Comments

@jerssonMA
Copy link

Lightweight Charts Version: 3.1.3

Steps/code to reproduce:
Encapsulating lightweight-charts in an external library.

Actual behavior:
I have my own library which encapsulates lightweight-charts and when installing it generates this error, I am using rollup to compress the files with a cjs format I cannot understand the conflict.

Expected behavior:
Module should be found.

I don't know what I am missing

Screenshots:

Error

image

Rollup config

image

@timocov
Copy link
Contributor

timocov commented Aug 7, 2020

It seems that rollup doesn't understand that it's module 🤔. Can you please create repro for that?

@jerssonMA
Copy link
Author

It seems that rollup doesn't understand that it's module 🤔. Can you please create repro for that?

It is a private library... I could not share this access 😔. Do you require something specific about the implementation?

@jerssonMA
Copy link
Author

It seems that rollup doesn't understand that it's module 🤔. Can you please create repro for that?

It is a private library... I could not share this access 😔. Do you require something specific about the implementation?

This error appears when including lightweight-charts in the rollup external config but if it is not included it generates this error:
image

@blazeyo
Copy link

blazeyo commented Aug 11, 2020

The error is there for webpack as well. I've tried adding "type": "module" to package.json but that causes other errors.

@blazeyo
Copy link

blazeyo commented Aug 11, 2020

Steps to reproduce:

  • yarn create next-app
  • cd my-app
  • yarn add lightweight-charts
  • yarn dev # it works
  • add import { createChart } from 'lightweight-charts'; to pages/index.js
  • restart yarn dev and visit localhost:3000
  • the app throws a syntax error
SyntaxError: Unexpected token {
    at Module._compile (internal/modules/cjs/loader.js:720:23)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:787:10)
    at Module.load (internal/modules/cjs/loader.js:643:32)
    at Function.Module._load (internal/modules/cjs/loader.js:556:12)
    at Module.require (internal/modules/cjs/loader.js:683:19)
    at require (internal/modules/cjs/helpers.js:16:16)
    at Object.<anonymous> (/tmp/my-app/node_modules/lightweight-charts/index.js:6:19)
    at Module._compile (internal/modules/cjs/loader.js:776:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:787:10)
    at Module.load (internal/modules/cjs/loader.js:643:32)
[...]/lightweight-charts/dist/lightweight-charts.esm.development.js:7
import { bindToDevicePixelRatio } from 'fancy-canvas/coordinate-space';

@jerssonMA
Copy link
Author

Steps to reproduce:

  • yarn create next-app
  • cd my-app
  • yarn add lightweight-charts
  • yarn dev # it works
  • add import { createChart } from 'lightweight-charts'; to pages/index.js
  • restart yarn dev and visit localhost:3000
  • the app throws a syntax error
SyntaxError: Unexpected token {
    at Module._compile (internal/modules/cjs/loader.js:720:23)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:787:10)
    at Module.load (internal/modules/cjs/loader.js:643:32)
    at Function.Module._load (internal/modules/cjs/loader.js:556:12)
    at Module.require (internal/modules/cjs/loader.js:683:19)
    at require (internal/modules/cjs/helpers.js:16:16)
    at Object.<anonymous> (/tmp/my-app/node_modules/lightweight-charts/index.js:6:19)
    at Module._compile (internal/modules/cjs/loader.js:776:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:787:10)
    at Module.load (internal/modules/cjs/loader.js:643:32)
[...]/lightweight-charts/dist/lightweight-charts.esm.development.js:7
import { bindToDevicePixelRatio } from 'fancy-canvas/coordinate-space';

My problem also occurs in a next-js application, I suspect it is due to a babel configuration but I cannot identify which one, this error also occurs when executing the unit tests with jest.

@timocov Do you know what the configuration could be? I understand that you use typescript, I suppose that when transpiling the code we have a configuration that we need to have in our babel.

@timocov
Copy link
Contributor

timocov commented Aug 14, 2020

Ah, it seems that I understand what's going on here. That's because you're trying to import that module in nodejs environment, which requires either commonjs or esmodules (mjs and full path with extension). You can try to import standalone version in nodejs (it doesn't have any import and is just iife).

Related issues #446 and #484.

Maybe @NekitCorp or @azhang can help here?

@azhang
Copy link

azhang commented Aug 14, 2020

Yea, agreed with @timocov. Looks like it's not parsing the import statement correctly because it's not the full path including .js extension. Otherwise i'm not sure - not familiar with Next.js and webpack does seem to support es6 modules natively

@blazeyo
Copy link

blazeyo commented Aug 15, 2020

Ok, this can be worked around with a dynamic import in next. As mentioned by @NekitCorp here libraries don't usually throw fatal errors when they're imported in the SSR context, so that might be worth fixing.

Thanks for the library and all your hard work. It's absolutely fantastic!

@timocov
Copy link
Contributor

timocov commented Aug 21, 2020

I think we need to add article in the docs for that (how to integrate in SSR context).

@timocov timocov added the documentation Improvements or additions to the documentation label Aug 21, 2020
@timocov timocov changed the title SyntaxError: Cannot use import statement outside a module DOCS: How to use in SSR context Aug 21, 2020
@miketeix
Copy link

miketeix commented Sep 1, 2020

Any idea on how this could be remedied in a Nuxt context? (#557 )

@timocov
Copy link
Contributor

timocov commented Sep 3, 2020

@miketeix lightweight-charts cannot be instantiated in SSR context (because it creates canvases and all work is done with them). Do Nuxt have somrthing like dynamic loading? If so, I think you can use it to load library via it.

@miketeix
Copy link

miketeix commented Sep 3, 2020

Hey thanks the tip @timocov, it worked for me by loading third-party script using vue-meta for nuxt (https://vueschool.io/articles/vuejs-tutorials/how-to-load-third-party-scripts-in-nuxt-js/)
Cheers!

@NekitCorp
Copy link
Contributor

NekitCorp commented Sep 17, 2020

@timocov As it seems to me, need to make another version of the library for CommonJS modules and then there will be no problems on the server side. Then there will be no need to describe DOCS.

Now at package.json#main set in "main": "index.js" what is the entry point for node:

if (process.env.NODE_ENV === 'production') {
	module.exports = require('./dist/lightweight-charts.esm.production.js');
} else {
	module.exports = require('./dist/lightweight-charts.esm.development.js');
}

but in lightweight-charts.esm.development.js the first line goes ES modules import:

import { bindToDevicePixelRatio } from 'fancy-canvas/coordinate-space';

which leads to the errors described above.

Example package.json files of another library, which is also used only on the client side:

"main": "lib/cjs/index.js",
"module": "lib/es/index.js",

@timocov
Copy link
Contributor

timocov commented Nov 12, 2020

make another version of the library for CommonJS modules and then there will be no problems on the server side

@NekitCorp what's purpose of importing the library directly on nodejs side? I hadn't a deal with SSR so I'm not quite know how exactly SSR on nodejs works. lightweight-charts just can't work on nodejs side, because it uses canvas elements mostly and don't know how to work in SSR, so I'd say the library should be imported in async way on nodejs side.

I agree that there is some issue with the library's package.json and index.js file - we shouldn't use commonjs for esm and vice-versa, thus we have to do one of:

  • generate commonjs bundle as well as esm one
  • remove main field from package.json, remove index.js file (which is cjs module basically) and add "type": "module" to the package.json (I prefer this one)

The question is - who expects and needs commonjs version of the library? Afaik all bundlers support and welcome esm version over cjs one. It looks like the library shouldn't be imported directly in nodejs context at all, isn't it?

Just wondering what's the best solution here might be...

@jcrben
Copy link

jcrben commented Apr 24, 2021

The question is - who expects and needs commonjs version of the library? Afaik all bundlers support and welcome esm version over cjs one. It looks like the library shouldn't be imported directly in nodejs context at all, isn't it?

I'm running into this running tests w/ jest which does run on node right? I ended up just ignoring it for now (as in https://stackoverflow.com/a/66340153/4200039) but at some point I would like to load this and run tests against it

@dkwolfe4
Copy link

dkwolfe4 commented Oct 1, 2021

The question is - who expects and needs commonjs version of the library? Afaik all bundlers support and welcome esm version over cjs one. It looks like the library shouldn't be imported directly in nodejs context at all, isn't it?

Just wondering what's the best solution here might be...

Svelete REPL for one. I'm running into this problem with bundler.js/unpkg.com and getting 'Error: Cannot find "/coordinate-space" in fancy-canvas@1.0.0' when using the following imports :

    import {CrosshairMode} from 'lightweight-charts';
    import Chart from 'svelte-lightweight-charts/components/chart.svelte';
    import CandlestickSeries from 'svelte-lightweight-charts/components/candlestick-series.svelte'; 

Not sure how Fiddle links on the demo page work, does they do successfully complete the import....

@raulvictorrosa
Copy link

import dynamic from 'next/dynamic';

const Chart = dynamic(() => import('@/components/Chart'));

I imported the component that create my chart this way, so it worked.

@darwin403
Copy link

@raulvictorrosa Hey, can you please share how this can be fixed for Next.js? I've tried with dunamic import, doesn't work. Here is the example with dynamic + lightweight-charts+next.js which simply doesn't work! :(

https://codesandbox.io/s/withered-meadow-2cvtn?file=/pages/index.jsx

@raulvictorrosa
Copy link

raulvictorrosa commented Dec 21, 2021

@raulvictorrosa Hey, can you please share how this can be fixed for Next.js? I've tried with dunamic import, doesn't work. Here is the example with dynamic + lightweight-charts+next.js which simply doesn't work! :(

https://codesandbox.io/s/withered-meadow-2cvtn?file=/pages/index.jsx

Actually I did the same way as in your link but for me just worked in the development env, but when I try to build the app the error happens again in the build process.

@raulvictorrosa
Copy link

raulvictorrosa commented Dec 21, 2021

@raulvictorrosa Hey, can you please share how this can be fixed for Next.js? I've tried with dunamic import, doesn't work. Here is the example with dynamic + lightweight-charts+next.js which simply doesn't work! :(

https://codesandbox.io/s/withered-meadow-2cvtn?file=/pages/index.jsx

Found here the solution bro, actually I put this way, disabling the SSR, so this way worked in the build process and in dev env.
This link can help also https://nextjs.org/docs/advanced-features/dynamic-import.

import dynamic from 'next/dynamic';

const Chart = dynamic(() => import('@/components/Chart'), { loading: () => <p>Loading ...</p>, ssr: false });

@anikashc
Copy link

@raulvictorrosa Hey, can you please share how this can be fixed for Next.js? I've tried with dunamic import, doesn't work. Here is the example with dynamic + lightweight-charts+next.js which simply doesn't work! :(

https://codesandbox.io/s/withered-meadow-2cvtn?file=/pages/index.jsx

This works btw

@mustaphaturhan
Copy link

mustaphaturhan commented Jun 28, 2022

For the people who use nextjs, if you don't want to use ssr: false -which is exclude lightweight-charts from getStaticProps build-, you may want to use next-transpile-modules instead.

  • Open your next.config.js file.
  • Export your config with using withTM hoc. Example:
/**
 * @type {import('next').NextConfig}
 */
const nextConfig = {...};

const withTM = require('next-transpile-modules')(['lightweight-charts', 'fancy-canvas']);

module.exports = withTM(nextConfig);

If you are using next 13.1 and later, please check #543 (comment) out.

@pezdel
Copy link

pezdel commented Sep 23, 2022

for astro you just need to do client:only="react"
https://docs.astro.build/en/reference/directives-reference/#clientonly

@0xAskar
Copy link

0xAskar commented Nov 17, 2022

SOLVED: using the implementation from @mustaphaturhan helped. i tried everything but that. thank you

Hi, I still get the same error as above in NextJS and react. I am trying to create a component and I build the component as I do from above even using dynamic load, but the problem comes from the lightweight library itself

To reiterate, without even importing this component anywhere, I get thrown this error, so the dynamic code isn't solving anything while this component just renders by itself.

import { bindToDevicePixelRatio } from 'fancy-canvas/coordinate-space';
SyntaxError: Cannot use import statement outside a module

Here's my code: The error occurs at the import { createChart } from 'lightweight-charts'; line

MainChart Component

import React, { useEffect } from 'react';
import { createChart } from 'lightweight-charts';

export default function MainChart() {
  const ref = React.useRef();

  useEffect(() => {
    const chart = createChart(ref.current, { width: 400, height: 300 });
    const lineSeries = chart.addLineSeries();
    lineSeries.setData([
      { time: '2019-04-11', value: 80.01 },
      { time: '2019-04-12', value: 96.63 },
      { time: '2019-04-13', value: 76.64 },
      { time: '2019-04-14', value: 81.89 },
      { time: '2019-04-15', value: 74.43 },
      { time: '2019-04-16', value: 80.01 },
      { time: '2019-04-17', value: 96.63 },
      { time: '2019-04-18', value: 76.64 },
      { time: '2019-04-19', value: 81.89 },
      { time: '2019-04-20', value: 74.43 },
    ]);
  }, []);

  return (
    <>
      <div ref={ref} />
    </>
  );
}

@tamebadger
Copy link

tamebadger commented Jan 19, 2023

using the latest next.js version 13.1 you can now solve this with editing the next.config.js in the following way:

module.exports = {
  transpilePackages: ['lightweight-charts']
}

more info here in the release notes of 13.1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to the documentation
Projects
None yet