billstclair/elm-websocket-client

Make JavaScript Code Work with Webpack

Closed this issue · 7 comments

I'm not an expert in JavaScript. As I use Webpack, I think, I can't have global variables. So I would like to be able to require your JS code through some module system. You can see my project here. The event-stream branch currently contains a version were I use WebSocket Client 2.x. There I managed to replace your global variable WebSocketClient with module.exports. But in your PortFunnel version, I'm not sure if I'll manage to fix this.

This one may take me a while, because it requires that I learn WebPack, which I've heard of but never looked at. But lots of people use it, so probably somebody on Elm Slack can help if I run into a brick wall.

I think it would be very beneficial to provide an init function for the PortFunnel modules like WebSocket.js. The problem is, what you have to load them in the right moment after PortFunnel.subscribe(app, ...) is called. Currently, I see no way to load everything and initialize afterwards.

I fixed your first comment in ac4f378. I'll make another comment, and close this issue, after I've fixed the documentation issues and published the dot release.

Thank you for this lesson. Now I need to update the other copies of PortFunnel.js. Any maybe I should have made an NPM package for it, but I think I'm going to keep this package free of dependence on NPM. Most Elm programmers have it, but it isn't required, unless you use elm-format or elm-test.

To address your second comment...

The PortFunnel modules themselves are loaded automatically, by the loadModule function in PortFunnel.js, using document.head.AppendChild(script). Since your Elm code should already be loaded when you call PortFunnel.subscribe(), they should have everything they need. I don't plan to support dynamic adding and removing of the Elm subscription to the PortFunnel Sub port. That needs to be there in the initial Browser subscriptions.

Do you have some other reason to delay the initialization of WebSocket.js?

I fixed the WebPack issue with version 3.0.2. I'll leave this issue open until we address the delayed init issue.

https://package.elm-lang.org/packages/billstclair/elm-websocket-client/3.0.2

Regarding to ac4f378, you are right. That works and is the same way as Elm works within Webpack:

let elm = require('./Main.elm');
let app = elm.Elm.Main.init({flags: flags});

Instead of having to write elm.Elm or in your example something like portFunnel.PortFunnel, it would be nicer to return the PortFunnel as module export. But than it wouldn't work as top-level script.

Regarding your module loading...

I would never do this. First, you load a separate file over HTTP instead of having everything inside a bundle, second, you dynamically insert new JavaScript code at runtime. I have a problem with that dynamic loading, because today the CSP header is available, which enables one to control JavaScript loading. With that you can effectively prevent XSS attacks by completely disallowing dynamic loading of JavaScript.

And now I understand your desire for an init function in WebSocket.js. You're loading it yourself, and want to delay its initialization until after you've called PortFunnel.subscribe(). WebSocket.js is also assuming that PortFunnel is global variable (or property of this), which may also not work for everyone.

I could probably make this compatible for you, but I'd have to change all my other PortFunnel modules, too. I suggest that you edit PortFunnel.js and WebSocket.js yourself to make them work exactly as you want. If I get lots of other similar requests, I'll consider updating all four PortFunnel modules, but right now it seems easier for you to just do what you need (well, it's easier for ME).

I'll see if I mange to get your PortFunnel.js and WebSocket.js working with my style of loading. I'll open a new issue, were I describe my desire to load the PortFunnel modules myself.