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

Use of fs at runtime prevents use in browser #546

Closed
Hasenn opened this issue May 28, 2022 · 4 comments
Closed

Use of fs at runtime prevents use in browser #546

Hasenn opened this issue May 28, 2022 · 4 comments

Comments

@Hasenn
Copy link

Hasenn commented May 28, 2022

In the context of a web app that reads various chordpro from different urls I would prefer having it parsed on the browser to have my app be distributed via a CDN than having to offer an API to proxy and parse the different songs.

But when doing that, i get this error

./node_modules/handlebars/lib/index.js:17:0
Module not found: Can't resolve 'fs'

Import trace for requested module:
./node_modules/chordsheetjs/lib/index.js
./lib/useChords.js
./pages/index.js

https://nextjs.org/docs/messages/module-not-found

my code just does this (client-side)

const parser = ChordSheetJS.ChordProParser();
const song = parser.parse(data);
const formatter = new ChordSheetJS.HtmlDivFormatter();
const disp = formatter.format(song);

Possible culprit is src/normalize_mappings/generate-suffix-normalize-mapping.ts which uses fs to read and write some things. I think this is part of some build-time codegen thing, in which case it shouldn't ask for fs at runtime maybe it gets bundled by mistake ?

@Hasenn
Copy link
Author

Hasenn commented May 28, 2022

also in bundle.js i get this

// Publish a Node.js require() handler for .handlebars and .hbs files
function extension(module, filename) {
  var fs = require('fs');
  var templateString = fs.readFileSync(filename, 'utf8');
  module.exports = handlebars.compile(templateString);
}
/* istanbul ignore else */
if (typeof require !== 'undefined' && require.extensions) {
  require.extensions['.handlebars'] = extension;
  require.extensions['.hbs'] = extension;
}

@martijnversluis
Copy link
Owner

Hey @Hasenn,

Thanks for reaching out. Indeed, the library as packaged node module is not suitable for use without build tool.

However, every recent release on GitHub includes a browserify'd JS bundle. Go to the latest ChordSheetJS release and download bundle.js. When including that file, it will expose a global variable that contains all functionality.

Below an example HTML file:

<html>
<head>
  <script src="bundle.js"></script>
</head>
<body>
  <script type="text/plain" id="chordSheet">
{title: Let it be}
{subtitle: ChordSheetJS example version}
{composer: John Lennon}
{composer: Paul McCartney}
{Chorus}

Written by: %{composer}

Let it [Am]be, let it [C/G]be, let it [F]be, let it [C]be
[C]Whisper words of [G]wisdom, let it [F]be [C/E] [Dm] [C]
  </script>
  <style>
    body {
      font-family: sans-serif;
    }
  </style>
  <script>
    const {
      ChordProParser,
      HtmlDivFormatter,
    } = ChordSheetJS;

    const parser = new ChordProParser();
    const chordpro = document.getElementById("chordSheet").innerText;
    const song = parser.parse(chordpro);
    const formatter = new HtmlDivFormatter();
    const disp = formatter.format(song);
    const css = HtmlDivFormatter.cssString('.chordSheetViewer');

    document.write(`<style>${css}</style>`);
    document.write(`<div class="chordSheetViewer">${disp}</div>`);
  </script>
</body>
</html>

This should result in something looking like this:

image

Please let me know if you need more info or experience any other issue.

@Hasenn
Copy link
Author

Hasenn commented May 29, 2022

Thanks for your answer,
Its nice that there is a way, but this is not ideal for me (in a react app) and it was kind of surprising that it worked that way, is this some consequence of using PEG.js ?
Maybe a tool like webpack be able to help having this library work on both server-side and browser ? I don't see a reason in what the library does to require server-side only capabilities like fs

@martijnversluis
Copy link
Owner

Ah sorry, I missed the part where you mentioned NextJS. For a NextJS (or any React) app, I would expect the build tool of your project to correctly handle this.

If I correctly read the stacktrace, the error occurs in the Handlebars module. Handlebars registers a handler for requireing .handlebars and .hbs files. However, that handler is not used by ChordSheetJS, those templates are compiled and baked into the single index.js.

It might be a Webpack issue, found some suggestions here: handlebars-lang/handlebars.js#1174

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants