Run-time bundling of ES6 modules in ASP.NET MVC - asp.net-mvc-5

Are there any existing solutions for run-time bundling of ES6 modules?
I'm looking to simplify JavaScript code development in a MVC5 web app. We're having issues with large, unwieldy JS files, so I'm hoping to get a module loader system in place. So far, I'm not finding any existing bundle transformers for ES6 or another module loader format. I'd be fine with using TypeScript or nodejs require style. I prefer not to use require.js style, though.
Perhaps there's a good reason this solution doesn't exist already. Maybe the dependency resolution processing is too much for a run-time bundling solution. But, I figure it's worth a shot to ask.
Solutions Considered
Prebuilt Web Client
Ultimately, this is where I want to be, but I need a stop-gap solution for now. I know how to put together a build system for an HTML client using grunt/gulp/webpack. But I don't want to have to tell developers to run webpack -w or something similar during development. Nor do I want to tell them to rebuild a solution for every JS change. They should be able to modify the file, refresh the browser, and see the change.
Directory Structure
This is the route I'll probably end up going with. Basically, this JS codebase consists of jQuery widgets and plain JS (helpers/common functions). So, if I structure the code in this directory structure and include the js dir, it should get me most of the way there:
js (DIR)
app-start.js
helpers (DIR)
widgets (DIR)
Widgets should be fine. Helpers, I can see issues where one function/class depends on another. Though, since a function call should never start with a helper (only a widget), this should work fine, assuming no globals are used (or maybe one global like 'App').

Related

Project too large

I'm just starting to learn Angular, I installed in my Ubuntu Linux:
Angular CLI: 7.1.4. and
Node: 10.14.2.
My question is, why one project is too large? I mean a simple "helloworld" is 334MB, I don't know why, Is it possible resize it? or delete any folder that is unnecessary? Or Is there something wrong with my installation? (how can I detect that?)
The bigger folder is node_modules, and when I create my projects, generates a lot of folders.
I was reading about "angular lazy loading", but I'm new.. It is not totally clear for me.
this is the folder spaces:
Please... I hope somebody can help me...
best regards
You might be using big bundles which are not needed, so you can break them up:
https://medium.com/#julienetienne/javascript-bundles-are-too-big-break-up-the-libraries-3be87d5ef487
In modern JavaScript, projects require modules that themselves require modules that require modules... resulting in node_modules directory with hundreds of dependencies. A 100Kb library might be included because someone needed one function from it. JavaScript is not compiled, so all that source tends to be rather big. This is an unfortunate, but unavoidable truth; your Angular project directories will be big, and there's nothing you can do about it. It is perfectly normal.
The good part: modern JavaScript deployment typically includes packing up those libraries with Webpack or Parcel or similar code bundlers. Most of them implement "tree shaking", which analyses the code to find only the functions that are potentially utilised starting from the entry point, and only bundle those, ignoring the rest. This means that 100Kb library whose one function is used is transformed into just that one function in the final distribution bundle.
Not all of the bundlers are equally good at it at this point. For example, Webpack cannot tree-shake the CommonJS modules, only ES6 ones.
You can remove node_modules folder when you are not going to use the app.
And, when you need work on the application, you can re-generate node_modules using the command: npm install
Those are just node-modules, they are needed for building the project, but not necessarily everything inside of them will be deployed to production. As Amadan said, there is a process of tree-shaking (filtering only used modules) and also in production you use the minified version of the same JS code (where for example whitespace is missing and variable-names are shortened), among other optimizations. A production-optimized Angular project should not be more than a 100KB for a hello-world application.
In the provided image I see packages like
selenium-webdriver
protractor
Those belong to dev-dependencies (see your package.json file) because they are used for testing. When building for production, no code from dev-dependencies should be included. The typescript package (which is nr.2 in size in your screenshot) will also not be present in production because types like string are only used for writing Typescript code, but the browser receives Javascript, which it is compiled to.

using requirejs without main file nor config()

I'm building an app that will contain many js (jquery) modules (files) using the following setup;
The build is run using Grunt task runner.
I use handlebars templates, then generate the html from *.hbs files.
During the build, I uglify all the js files into one minified file.
I call the minified file in my application <script src="assets/js/app.min.js"></script>
Now, I want to use requirejs to organize my code and adhere to the AMD specifications..
But I got 3 problems with this approach:
I need to have 1 single minified file for all the js; this keeps my code harder to "decode" thus to copy (since it is mixed with other dependencies; jquery, modernizer..) and also helps avoid extra http requests if scripts are called individually.. However, requirejs needs a main file to initialize the app and inside that main file It calls the other required files.. I don't have such configuration.
Many of the dependencies I'm using are in a bower package (that I don't include in the distribution); this makes it not possible to call those files using the suggested requirejs method.
I'm using jquery on this with some 3rd party plugins that don't call define(); to make them work I have to use shim config which again rises the problem #2!
So how am I supposed to take advantage of requirejs while keeping my code in modules and well organized?
Sorry for the long question and thanks for reading :)
ps: Feel free to change the title of the question as I couldn't find a better one!
I finally opted for AngularJS as it adheres to my setup above and allows me to split my app into manageable small modules.
I have also the possibility to use the ease of jQuery (even though it is not a best practice among angular community) and much more.

Sharing code between node js project and a web site project

So I started coding a chess engine in typescript as a side project. I initially intended it to be a CLI like most other chess engines that interact through stdin and stdout. This so I could plug it to a GUI like Arena and test it against other engines. For that I decided to do it as a node project.
I set it across several files with 1 being the UCI (universal chess interface) implementation and the remaining ones chess logic and AI logic. After banging my head a few times trying to understand modules in typescript I finally got it to work.
Now I decided it would be interesting to write a simple GUI myself as a webpage with html+typescript+jquery. Now, I would like to use all the logic modules I wrote but I'm finding it impossible. From what I understand you can't use CommonJS in browsers so the only way I could get it to work was using instead internal modules for which I need to modify the .ts files to wrap the code in module X{ } blocks and recompile them just for the GUI every time I change something. This situation seems far from ideal and I was wondering if there is a way around it...
Use http://browserify.org/ to add CommonJS-like support on the front-end.
But also read this (slightly outdated) question and answer: How should I go about writing a node.js web application with both server and client side code?
Use external modules for both the server and the browser.
When compiling for the browser, use the switch to specify the AMD module pattern:
tsc --module amd app.ts
And use RequireJS to load modules for you.
<script src="require.js" data-main="app.js"></script>
You will need to compile for the different targets, but the source code in TypeScript can be identical.
I created a demo project to share code between the client and the server : https://github.com/basarat/demo-fullstack/blob/master/src/Gruntfile.js
It compiles the common files for both amd/commonjs and server files only as commonjs with the client only files as only amd. It uses grunt-ts to manage this : https://github.com/grunt-ts/grunt-ts

How to share common client-side javascript across NodeJS projects?

I'm a Node n00b starting a couple web app projects using Express, and I've got some common client-side libraries I'd like to share between the two projects. This seems like a very common problem, so there must be several solutions available already.
I come from a java background, and in java, I'd create a separate "common" project and "overlay" common WAR over my project during packaging. This would also allow for r.js optimization during the build process.
My best guess in Node is that I need to create a private NPM module, and map those common files into express via a use() middleware plugin. Is that right?
How, then, can I package both my common and project specific javascript into a minified file using r.js?
Or is source control the answer? Checking out my "common" repository inside each project?
Any help would be most appreciated. Thanks.
This seems like a very common problem, so there must be several solutions available already.
Good news: Yes, this is a common problem. Yes, there are several "solutions".
Bad News: All of the "solutions" are at least partially terrible.
Here's my advice:
1) Individual .js files should be coded as CommonJS modules
2) Groups of related .js files should be made into npm packages
3A) Use them in node via the regular node.js/CommonJS require function and use browserify to use them in the browser
3B) OR use a built tool like grunt to wrap commonjs into AMD format for use with requireJS in the browser
3C) OR consider something like component.io components

packaging node.js modules with more than code

I'm putting together a module I'd like to release, but am a bit stuck on how best to go about packaging it up. In addition to server side javascript, the module will need things like an admin screen, and client side javascript files. That is, it needs to serve out a fixed set of static html/css/js files. (I may have the node-static module as a dependency)
I'm curious what is the best way to handle this. I'd like to make this simple to install and integrate into apps, without forcing the user to dig through a long README. Basically they should be able to NPM the module, then add a line or two of code in the relevant place, and have it "just work". I don't want them to have to download other stuff, tell the module where to find the static files, etc.
Also, I'd like to make sure it can be included in both simple apps (i.e. one step from the standard "hello world") as well as complex apps using frameworks etc like Express, without undue hassle.
Is this possible, or is this beyond the scope of what the module system is designed to handle?
Once your package in installed with npm install mypackage -g you can use __dirname inside your executable to find the directory it's running in.
Likely /usr/local/lib/node_modules/mypackage/bin/mypackage
With your assets in /usr/local/lib/node_modules/mypackage/assets
so __dirname + '../assets' + myasset should correctly find your asset

Resources