What's the best way of including a node module on my webpage?
Should I use absolute paths like <script src="../../node_modules/bootstrap/dist/js/bootstrap.min.js"></script> or is there an easier and better way of doing it?
Thank you.
Add this in your app.js-file
app.use('/placeholder', express.static(__dirname + '/node_modules/'));
This allows you to write:
<script src="/placeholder/bootstrap/dist/js/bootstrap.min.js"></script>
And Node will redirect that path to the node_modules folder.
You can change placeholder to whatever you want, mine is named scripts
Node modules are designed for server-side execution in the NodeJS environment, not for use in a browser. So the best way to include them in a web page is not to.
I will note that Bootstrap is a client-side framework, so it makes no sense as a NodeJS module in the first place.
If you're looking for an npm-like tool for client-side packages, the flavor of the week is Bower.
My answer to this question would be a bit different and a little advance.
Maybe it won't be helpful to you right now, but definitely, in future, it will. Also, it would help out others.
Yes, the first answer is absolutely correct, you can add a placeholder and then add links relative to it in your index file.
Now, are you using a task runner like gulp or grunt? If not I would recommend you to start using it, because you can cut out a lot of manual work use these tools and eventually save a heck load of time.
You might be thinking why am I talking about gulp or grunt over here. I will answer this questing shortly.
Since you are using node.js, you already know how modules are loaded in Node.
eg : require('express');
What if we could use this approach for our client applications? You would only have to include one js file in your html and that js file would require all the other js libraries for you.
Great, suddenly you can reduce the number of script tags in your html page from approx around 20-30 to 1.
This is where module loaders come into picture.
But browsers do not understand the require statement.
To deal with this we use a tool called a browserify, we can use gulp(which I talked about earlier) to configure a task to browserify our files.
When you use this, you will have to require all your js libraries and your own js files into a single file (say: app.js). But as we said browsers do not understand require. This is where browserify will take this app.js file pre process it and spit out a single file that should be included into your html.
You can follow this article to get a clear picture on how to achieve this.
Scalable app using Gulp and browserify.
Pretty neat right! :)
Some of the other module loaders are System.js and webpack
Related
This is vague - I apologize in advance, I am trying to be as succinct as I can with my limited understanding, while exposing my potentially incorrect assumptions.
I have a website that's literally one huge HTML file. It runs scripts defined in-line in a <scripts> tag.
My goal is to move all the scripts into individual .js files and pull them into index.html (or into one another where required). I am familiar with the usage of Node's require and I am familiar with import, as used in Angular. I stress usage because I don't really know how they work.
Assumption 1: I cannot use require - it is purely for Node.js. The reason I bring it up is that I am pretty sure I have seen require in AngularJS 1.5 code, so assuming makes me uncomfortable. I am guessing this was stitched together by WebPack, Gulp, or similar.
Assumption 2: I should use import, but import only works with a URL address, if I have my .js hosted on a server or CDN, it will be be pulled. BUT, I cannot give local pathing (on the server) here - index.html will NOT automatically pull in the dependencies while being served. I need npm/Webpack/other to pre-compile my index.html if I want the deps pulled in on the server.
Assumption 3: Pre-compiling into a single, ready-to-go, html file is the desired way to build things, because the file can be served quickly (assuming it's ready to go). I make the assumption with the recent trend of serving Markdown from CDNs, the appearance of the JAMstack, and the number of sites using Jekyll and such (though admittedly for traditional Jekyll sites).
Assumption 4: I also want to go to Typescript eventually, but I assume that changes nothing, since I will just pull in TS to compile it down to .js and then use whatever solution I used above
Question: If it's clear what I am trying to do and what confuses me, is a decent solution to look into npm/Webpack to stich together my .js files? What would prepare them for being stiched together, using import/export? If so, is there an example of how this is usually done?
As you mentioned, require cannot be used for your purposes, since it is a part of CommonJS and NodeJS's module system. More info on require can be found here: What is this Javascript "require"?
Import is a ES2015 standard JS syntax. But ES2015 standard and everything above it has very limited browser support. You can read more about it here: Import Reference
However, you can still code in the latest standard (thereby enabling the use of import/export etc.,) and then transpile the code to be able to run on the browser. Inorder to do this, you require a transpiler. You can refer Babel which is one of the most popular transpilers : https://babeljs.io/
For your exact purpose, you need to use a module bundler. Webpack/Rollup etc., are some popular module bundlers. They can automatically identify all the JS files referenced through import, combine them and then transpile code to be able to run on the browser (they also use a transpiler) and produce a single JS file (or multiple, based on your configurations).
You can refer the getting started guides of Webpack: https://webpack.js.org/guides/getting-started/
or RollupJS: https://rollupjs.org/guide/en#quick-start
I'm new to Browserify and I'm trying to figure out how to make it more efficient with regards to how much the client needs to download.
I have a web app, that uses many different 3rd party libraries and custom code. With Browserify, it seems like the general approach people suggest is to wrap everything up into one big bundle.js. This seems horribly inefficient to me for several reasons:
For example, lets say your bundle.js contains lib1, lib2, lib3, customLib.
If a part of your web app only needs lib1 the client still has to download a huge bundle.js and it ends up not using 75% of it. Wasted bytes downloaded. Unnecessarily increased page load time.
If your customLib is a piece of code that you iterate upon often, then every time it changes, your clients have to redownload bundle.js, again downloading a ton of 3rd party libraries that haven't changed...
Other parts of your web app may use lib2 and lib3 but the client may or may not ever go to there, in which he definitely wasted bandwidth downloading the entire bundle.js.
I've seen suggestions to split up your bundle into multiple bundles. But to what end? If one page uses lib1, another page uses lib1 and lib2 and another page uses lib2 and lib3, then how do you split it up? The more you split it up into multiple bundles aren't you getting away from the advantages of bundle.js?
Browserify seems to be highly regarded so I hope that I am just missing something here. What is the proper approach to bundling together many libraries and custom scripts together? People call Browserify a "script loader" but every script loader I've seen in the past (like yepnope etc), use logic to determine which scripts to download, which seems like a much more efficient solution, while Browserify appears to want the client to download everything...
Not sure if the answer fits SO format well. But nevertheless...
Partitioning Section of handbook describes 2 following techniques
factor-bundle factors 2 or more entry points placing common dependencies into a single bundle.
partition-bundle same as factor-bundle but with runtime loading using async loadjs function.
Factor bundle
<script src="/bundle/common.js"></script>
<script src="/bundle/x.js"></script>
Partition bundle with async loading fallback
loadjs(['./x'], function(x){...});
Substack just published this gist explaining how to split bundles. He suggests to use factor-bundle like this:
browserify x.js y.js -p [ factor-bundle -o bundle/x.js -o y.js ] \
-o bundle/common.js
Browserify great and all, and makes it really sweet (even compared to require.js), but the idea of bundling everything into one minified file although sounds great for final version of the app, feels like something I would like to avoid during development. Wouldn't it make difficult to debug stuff?
Is it possible to use browserify and still keep all javascript files and make it more transparent for the browser during development? And when you ready to ship it run browserify bundler and minify everything into one file?
Or maybe there's better approach - like keeping all scripts listed in a partial that gets included to the main page for development or something like that?
Upd: I just found that there's an option:
--debug -d Enable source maps that allow you to debug your files separately.
Is that helpful? I guess it is. But I suppose it still makes it difficult if want to use coffeescript source maps
Indeed you shouldn't use minified/concatenated Javascript in development. Luckly there are a myriad of ways of solving this particular issue, I recommend taking a look into an automated build process like Grunt.
I've been using a grunt file to concatenate all my JS into a single file which is then sent to the client. What advantage do I have in using require calls then? The dependencies are inherent from the concatenation order and I don't have to muddy all my JS with extra code and another third-party library.
Further, backbone models (for example) clearly state their inheritance in their definitions. Not to mention that they simply wouldn't work if their dependencies weren't included anyway.
Also, wouldn't maintenance be easier if all comments related to dependencies were in one place (the grunt file) to prevent human error and having to open every JS file to understand its dependencies?
EDIT
My (ordered) file list looks something like:
....
files: [
"js/somelib.js",
"js/somelib2.js",
"js/somelib3.js",
"js/models.js",
"js/views.js",
"js/controllers.js",
"js/main.js"
], ...
So perhaps requireJS isn't worth it for small projects anyway.
Using require.js allow you to break down each part of your application into reusable modules (AMD) and to manage those dependencies easily. It is not easy to manage dependencies in a javascript application with 100 classes, for example.
Also, if you don't want all the overhead of require, check this out (developed by the same guy who created require.js): https://github.com/jrburke/almond
The answer depends on the size of your app and the end use case..
A single site.min.js payload for the front end (client) generally aims for small file sizes and simple architectures (1 single file generated from maybe 10).
back end based (server) apps are usually much bigger and complicated and therefore may warrant the use of another tool to help with managing large code libraries and dependencies (50 files for example).
In general, RequireJS is worthwhile but only if you have many files and dependencies. An alternative for use in the client would be almond. Again, using a tool like this must warrant the need (many files and dependencies).
The answer from orourkedd is also worth reading.
Quick note - by versioning I mean for the purposes of cache busting. The common practice of adding query params to the end of the script request does not work on all browsers. The easiest and the most messiest way that I have found to date is to version my entire deploy folder name.
-- scripts.v1
-- scripts.v2
But this is incredibly messy and mucks up the deploy times too (I use S3 as my cdn). Does anyone know of an alternate method to this?
EDIT
It seems, I have not been very clear. Let me be a bit more explicit.
I use requirejs on my site. It is quite a JavaScript heavy application with frequent updates and iterations. With requirejs in place now, the only way I can reliably make sure that browsers are serving the latest version, is to version my whole deploy folder name (javascript) and upload the whole lot of files to S3 again. I then use the data-main method to set the base path of the project.
For many reason, this is quite cumbersome. Even if the code change is just a few lines, the whole process has to be repeated. Is there some other decent method to let requirejs know that files have versions? As in, if I call
require(["superImportantJSFile"], function(){})
it will know that the current version is superImportantJSFile.v4.js or something along those lines.
I hope I have been more clear now. Any suggestions as to how the community in general does this? I'm pretty sure this has to be a common scenario, but I haven't been able to find a good solution to this yet
I like to use a post-build step that puts static resources into a folder with a path that includes the version control version number. For example source control revision number 1234 would lead to the creation of a path: /1234/scripts/*. These directories are also created in the CDN with the correct version of the assets within.
In our require.js config in a template, we replace the baseURL with the appropriate revision, which is controlled via a config file, eg:
var require = {
baseUrl: "%%resDir%%",
...
};
This makes it easy to change the asset versions between a few different releases, which can all stay on the CDN without causing any conflicts. It also solves the browser cache busting issue.
The HTML5 Boilerplate offers one of the most graceful solutions I have seen. They have configs available for Apache and nginx. From there you can just add a timestamp to the filename within your script tags, like so:
<script src="scripts/app.20130728.js"></script>
Which the web server would rewrite to scripts/app.js.
You can add aliases to your RequireJS configuration by using map (see http://requirejs.org/docs/api.html#config-map) for example:
require.config({ /* ... other config.... */
map: { '*': {'superImportantJSFile': 'superImportantJSFile.v4'} }
})
So you only have one place to update :)
You mentioned the use of a CDN which is a good use case to not put those files in your minimized r.js bundle (in case that you are using that tool). But if those files are updated frequently, maybe it makes sense to pack your modules with r.js and update the whole code.