We're migrating from Require JS to webpack. In our project, we were able to require a runtime-based url as a module (to our SignalR proxies - these are generated at runtime) and that file was downloaded completely before the module requiring that fired off. I haven't-yet determined how to achieve the same effect using webpack except for an unsavory syncrhonous xhr request to get the script, which is a deprecated approach. What am I missing?
So the desired effect is to be able to have the top-most consumer require a module which internally requires the core SignalR lib (which we get like normal) and then this runtime-based (that url) script as a module, before running the top-most consumer's code.
Related
I'm trying to follow the Compose Multiplatform Web Getting Started guide. Most of it seems to work fine, but when I try to actually run the thing (gradle jsBrowserRun), it starts a browser, but it can't find the generated JavaScript file. The browser console shows a 404 for GET http://localhost:8080/kotlin-multi-web.js.
The file kotlin-multi-web.js is indeed the name of a file generated in web/build/compileSync/main/developmentExecutable/kotlin.
The page title matches the one I defined in my index.html, so that gets loaded correctly.
I have tried a pure Compose Web project (which isn't a Gradle multi module project), and there it does all load correctly. I checked, and didn't see any differences between the Gradle build files other than the extra dependency from the web project on common.
So, why doesn't it load, and how can I fix it?
I am building a micro front-end using Vue 3, Typescript, and Vite and for this, I have a wrapper in single-spa, let's call it wrapper.product.com.
And I also have a micro front-end, let's call it A, so it is placed at a.product.com and it is built using code split.
The problem is that A only works with referenced dependencies. Therefore, when A tries to get assets/somefile it tries to fetch from wrapper.product.com/assets/somefile.
I am also using the build.base in the vite.config.ts to mention the right domain, but it didn't work.
I know there is a possible solution using webpack (systemjs-webpack-interop) but is it possible with Vite?
Any ideas to fix this and have all dependencies of A being fetched from the A domain?
I use Browserify at the moment to bundle my client-side modules into bundles. Each bundle is then loaded as a script tag.
However with HTTP/2, my understanding is that bundling and minification are no longer best practices due to the amount of simultaneous connections available between the client and the server.
So how do I load npm modules in the browser without bundling?
I guess I want to be able to do
var someModule = require('some-module');
And have 'some-module' fetched from the server dynamically.
(I am aware there may be adverse affects on older HTTP/1.1 clients.)
You can't (without hacks and/or rewriting the files), because CJS require is sync. Even if you could, it would still be slow.
JS thread needs to be suspended waiting for the dependency to be loaded and executed. Without modifying source files doing this would require hacks like sync XHR or document.write, but these won't be able to load dependencies in parallel.
You could theoretically use some tool to rewrite the files to convert imperative require to callback-driven one (sort-of like conversion of CJS to AMD or ES6 yield compilers for ES5), but that would probably defeat your goal of using npm modules as-is.
And finally, even if you could load them (or used ES6 modules and travel a bit to the future), it would still be slower than bundling, because the browser doesn't know the full dependency tree, so it has to wait to discover dependencies of dependencies.
I do recommend webpack chunking (use the analyzer to find chunkable parts of the app) if you'd like to load your app in smaller pieces. It requires using an async require.ensure(cb) though.
Depending on what you're using to build your JS into a useful browser bundle, the tools will vary.
If you're using webpack, they have a built in feature for lazy loading:
https://github.com/webpack/bundle-loader
If you're using browserify, there is a module called externalize that aims to do this:
https://github.com/epeli/browserify-externalize
If you're using something else, I'd recommend searching for that builder's name and "lazy loading". I know RequireJS has supported this for a long time, too.
When you load with Dojo's require a module with the wrong module url (mid), it creates an error (timeout) each time you use require(not loaded yet modules) again, regardless you loaded another module successfully afterwards.
Is there a way to clear that errors? Those failed modules seem to be permanent somewhere in dojo.js and they don't seem to be accessible through an API.
ps: I'd be happy even with a core hack to get rid of them.
Is it possible to use Dojo build without the need to modify JavaScript files?
The article dgrid and Dojo Nano Build provides the instruction to create the build, but it requires adding the following line into JavaScript file, which initializes the application:
require(['dgrid/dgrid'], function () {
(replacing 'dgrid/dgrid' with your build module name).
However, it is very problematic when using build for own modules, because, of course, in development mode the require with own layer can't be included, otherwise the modifications made to own modules wouldn't be visible. But in production mode this line must be added.
So either you must modify the file manually before production build, or write a script that would modify the file during the build. Both are very error-prone.
Is there a better way to achieve that result? Is it possible for Dojo to recognize that the build is provided and should be used, instead of loading each module separately?
The following line of code can be included in both development and production modes.
require(['dgrid/dgrid'], function () {
I describe the reasons why in my answer here.
What you need to do is configure Dojo differently based on what environment.
In a blog post that I wrote, I describe this in more detail. The following summarizes the post:
I create three modes: Production, Uncompressed, and Development.
Development
When developing code, I will have the js source linked into the web server and the Development mode will point to the dojo.js file and the raw css file(s). The browser will load modules that I need using xhr. And I point to the top level css files which import other css files. The result is that a lot of requests will be made to the server and the loading of the page will be noticeably slow. The benefit is that you can see development changes without having to do a full build.
Production
Production mode points the main dojo file at the dojo.js that is built using the build tool. I also create <script> elements for the other layers that are needed in the page. I point the css to the built css files which the build tool has inlined the imported css. The page loads quickly, but it is difficult to debug
Uncompressed
Similar to production, but I point to the .uncompressed.js files. Production and Uncompressed are available in the released version of our software. I use uncompressed when trying to troubleshoot an issue in a production environment. The value of this mode is dwindling as the developer tools are better supporting compressed javascript (ie source maps, etc.)
Server side
The default mode is Production, but I use a query parameter to switch modes. I also store the current mode in the session, so that I only have to set the mode once to change it. Subsequent pages will run in the changed mode, until I change it back.
Here is a java implementation of this code.