nxus / clientjs

Client JS compilation for Nxus applications
1 stars 0 forks source link

Template action to 'require' or 'import' JS using the source code path, handling the bundle() call for you. #8

Closed ScottMaxson closed 8 years ago

ScottMaxson commented 8 years ago

Suggest something like a tag or directive in the EJS template that takes as a parameter the path to JS file(s) in the source tree.

If this could also call the clientjs bundle() to perform transcoding, it would be handy and keep from needing to cross-reference the source + target paths between various lines of (server-side) JS source code.

mjreich commented 8 years ago

đź‘Ť

I was thinking about something similar. To be more specific, this could be a template API/helper to be used in both the template and the code

app.get('templater').includeJS("my-template-name", __dirname+"/client/someFile.js")
<h1>My template</h1>
<%- includeJS(__dirname+"/../client/someFile.js") %>
loppear commented 8 years ago

Original documented intention was to use the scripts renderContext to do this all in one place, ala:

let output = '/static/path/file.js'
app.get('clientJS').bundle('/path/to/js', output).then(() => {
  app.get('templater').on('renderContext'), () => {
    return {'scripts': output}
  }
}

I'm not opposed to providing a helper, but want to better understand the case where this should be per-and-within-template (this is also setting up a static path with router, and firing the bundler, which needs to happen long before template rendering in most cases, so I'm not sure about an ejs helper specifically).

mjreich commented 8 years ago

@loppear I think the use case is where we have specific in-page react components and want to load those components only on certain pages (either because of conflicts or to reduce page load time). For a single Flux/Redux app, this probably isn’t an issue, but where we have pages with a map, multiple charts, etc, we’re loading up multiple scripts.

I think a valid issue Scott raises is managing the output URLs is a common place to introduce bugs (I often get the output url wrong in one place or another), so having that auto-generated and injected by ClientJS would be handy.

I think all this would be additive to the current API, rather than a replacement.

For Example, on another project:

    this._app.get('clientjs').bundle(__dirname+"/client/sparklines.js", "/public/js/source-sparklines.js")
    this._app.get('clientjs').bundle(__dirname+"/client/trends.js", "/public/js/source-trends.js")

    this._templater.on('renderContext.source-report', () => {
      return {scripts: ['/public/js/source-sparklines.js', '/public/js/source-trends.js']}
    })

would become

    this._app.get('clientjs').injectJS("source-report", [__dirname+"/client/sparklines.js", __dirname+"/client/trends.js"])
loppear commented 8 years ago

Yep, no issue with wrapping these examples in a new provider-helper (that is called in module startup), in either case repeating output URLS in your template is to be avoided.

ScottMaxson commented 8 years ago

The idea came as I was re-writing a bunch of hard-coded paths in gwli app, after updating to the latest nxus-clientjs which had a different way of setting the default access path for client side JS bundles. So it's primarily a request to hide details of the server side file-path to URL mapping, at least as requested. All good ideas here, though I understand implementation of some kind of directive in the template could require some kind of pre-scan of the template. Hadn't thought through all the implications...

mjreich commented 8 years ago

Holding on the EJS helper, as this has the potential to either: a) block the page until the script is browserified, b) render the page while the script is still building, causing a 404 on client load.

Answer is to use the includeScript method on ClientJS.