I'm wondering if someone can check my understanding of what the intended purpose of HTML5Boilerplate js directories. I understand that main.js is where I'm expected to place all site specific javascript that I author. Plugins.js is where I would place all jQuery plugins used. Both main.js and plugins.js will be concatenated and minified by the build process. Vendor.js holds javascript libraries. This directory will be minified (unless it is already minified) but not concatenated.
If this is true, then my question is where should something like cute slider which has a modular structure be placed? I'm thinking I want it to be minified and concatenated so it shouldn't go in the vendor directory. I don't believe I can add cuteslider's javascript to main.js or plugins.js without destroying it's modular structure. Should I create a new directory, and call it something like apps, to hold cuteslider code and then modify the build code to minified and concatenated it?
Here is a snippet of cuteslider's code structure
cute
cute.2d.module.js
cute.canvas.module.js
cute.css3d.module.js
cute.gallery.plugin.js
cute.slider.js
cute.transitions.all.js
First you have to consider cuteslider as a plugin.
Add the required files to make the plugin working (cute.slider.js, cute.transitions.all.js and respond.min.js) in the plugins.js.
Then add the js to load the slider into your page in the main.js as
$(document).ready(function() {
// code here to load cuteslider
});
The modular look have to be set only in the main.js file.
Related
I have a very old AngularJS project which is quite big. Instead of creating a bundled .js file composed of all the required code, this project is organized in the following way:
All the .js files are directly loaded in index.html with a <script src="path/to/js">
Even the dependencies minified .js files are loaded in the same way, examples:
<script src="bower_components/angular-route/angular-route.min.js"></script>
<script src="bower_components/angular-resource/angular-resource.min.js"></script>
<script src="bower_components/angular-cookies/angular-cookies.min.js"></script>
The code makes vast use of definitions (functions, classes, enums and so on) declared in different .js files without importing them (because they are all available globally). Examples:
// inside one file, PastFuture is not declared here
if (self.pastFuture === PastFuture.FUTURE) {
... // do something
}
// inside another file, it is not exported or anything, it is just defined
const PastFuture = {
PAST: 'PAST',
FUTURE: 'FUTURE'
};
I want to migrate this project into something a bit more "standard". I've removed bower for npm dependencies but now I'm stuck at forcing all these .js files to get bundled together.
The major problem of the code is that once bundled with browserify, all the definitions not imported stops working, for example, PastFuture is not defined unless I import it manually wherever is required.
Is there a way to overcame / solve this problem without adding exports and require in all the files of the project?
I was thinking that if I concatenate all those .js files instead of trying to make them require each other, it would have the safe effect without the need to add exports and imports.. but as a solution, it just sounds like a hack to me and I was searching for something more correct.
I am using react starter kit for client side programming. It uses react and webpack. No index.html or any html to edit, all js files. My question is if I want to load a vendor js lib from cloud, how to do I do that?
It would be easy to do that in a html file. <script src="https://forio.com/tools/js-libs/1.5.0/epicenter.min.js"></script>
However, in js file, it only uses npm installed packages. How can I import the above lib with no html file? I tried import and require, they only work for local files.
update 10/21/15
So far I tried two directions, neither is ideal.
#minheq yes there is a html file sort of for react start kit. It is html.js under src/components/Html. I can put cloud lib and all its dependencies there like this:
<div id="app" dangerouslySetInnerHTML={{__html: this.props.body}} />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="https://forio.com/tools/js-libs/1.5.0/epicenter.min.js"></script>
<script src="/app.js"></script>
<script dangerouslySetInnerHTML={this.trackingCode()} />
</body>
Good news is it works, I don't need do anything else in js file, no import or require. However, now I have two jquery libs loaded in different ways. One in here, the other through npm and webpack. I wonder it will give me trouble later. The react-routing I use give me 'undefined variable' error if I type a none home path in browser window due to the server side loading I guess. So this solution is not very good.
Use webpack externals feature. This is documented as: link. "You can use the externals options for applications too, when you want to import an existing API into the bundle. I.e. you want to use jquery from CDN (separate tag) and still want to require("jquery") in your bundle. Just specify it as external: { externals: { jquery: "jQuery" } }."
However, the documentation I found a few places are all fussy about how to do this exactly. So far I have no idea how to use it to replace <script src="https://forio.com/tools/js-libs/1.5.0/epicenter.min.js"></script> in html.
externals is not intended to let you do this. It means "don't compile this resource into the final bundle because I will include it myself"
What you need is a script loader implementation such as script.js. I also wrote a simple app to compare different script loader implementations: link.
var $script = require("scriptjs");
$script("//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js", function() {
$('body').html('It works!')
});
You can create a script tag in your JS as
$("body").append($("<script src="https://forio.com/tools/js-libs/1.5.0/epicenter.min.js"></script>"))
There is one html file that is definitely being used to serve to users with your js bundle attached. Probably you could attach the script tag into that html file
Use webpack's externals:
externals allows you to specify dependencies for your library that are
not resolved by webpack, but become dependencies of the output. This
means they are imported from the environment during runtime.
I have looked around for a solution and most of all proposals were based on externals, which is not valid in my case.
In this other post, I have posted my solution: https://stackoverflow.com/a/62603539/8650621
In other words, I finished using a separate JS file which is responsible for downloading the desired file into a local directory. Then WebPack scans this directory and bundles the downloaded files together with the application.
gulp.task("compile-vendor-js", function() {
return gulp.src("./bower_components/*/*.js")
.pipe(concat("vendor.js"))
.pipe(gulp.dest("./build"))
});
This gulp task will compile bower solved dependencies.
The problem is, it will consider all JS files, including the minified ones, making my build file have duplicated code.
I know that one solution for this is having a variable array containing all file paths, but this isn't good.
try something like:
gulp.src(["./bower_components/*/*.js", "!./bower_components/*/*.min.js"])
where you can find a common denominator between all the minified js files (eg, .min.js)
I think that a blacklist of files is going to be shorter than a whitelist in this case.
Also, you might consider looking into the main-bower-files project, which will read your bower.json file and pull out the main js files from each project for you.
I have a simple Dojo application, that does only one require call, loading all the dependencies. The trouble is, while it is extremely simple, it still ends up loading ~100 files from server. I tried to solve that problem using Dojo build system, but seems I don't have a deep enough understanding.
So my question is - given a list of dependencies, like the following:
["dojo/parser",
"dijit/registry",
"dojo/dom",
"dojo/on",
"dojo/query",
"dojo/dom-class",
"dojo/request",
"dijit/form/ValidationTextBox",
"dijit/form/Select",
"dijit/form/NumberSpinner",
"dijit/form/CheckBox",
"dijit/layout/ContentPane",
"dijit/Dialog",
"dojo/NodeList-traverse",
"dojo/domReady"]
how do I set up the build to create a single-file (or several-file, just not 100-file) dojo file?
If you're using Dojo's require() loader, there are build tools that you can use to combine files and minify. According to the site, the build tools aren't included in an official release, so you'll have to get them from the development version (specifically, look in the buildscripts directory).
The Dojo documentation contains some info on its build system that you may also find useful.
As a proof of concept, here are the steps I took:
Go to the download page, and download the Source Dojo Toolkit SDK (it's the only one that contains the util scripts needed for a build).
Extract to a location (for the sake of this post, let's say it's /opt/dojo-toolkit).
From the Dojo toolkit directory (i.e. /opt/dojo-toolkit), run the build util: ./util/buildscripts/build.sh action=release htmlFiles=/path/to/my/index.html (careful, this slowed my 5-year-old dual-core to a crawl)
Example of index.html (this one is exactly inside the dojo-toolkit directory):
...
<head>
<script src="dojo/dojo.js"></script>
<script>
dojo.require("my.test");
</script>
</head>
...
The require() call looks for nested modules (I couldn't get it to work with a top-level module), so in this case, I've got a my directory inside of dojo-toolkit which contains a test.js file. That file is the main "bootstrap" file which loads in all of the dependencies. I just put random require() calls in mine:
dojo.require('dijit.ProgressBar');
dojo.require('dijit.Tree');
And that should do it. Basically, running the build utility against your HTML file (the one that contains the reference to dojo.js) makes sure that all of the dependencies are found, starting from the top.
Note: the build system create a release directory with the built output, but it looks a little misleading at first - it appears to have minified each individual file, but if you look at your actual bootstrap file (my/test.js, in this case), it will be a combined, minified file with (I presume) everything you need to run your app.
Otherwise, if you're using AMD style require()'s (as in require.js), you can use its optimization tool. According to the site, it will:
Combine all dependent files (including require.js itself) into a single file. It analyzes the require() call to figure out which files it needs to combine.
Minify your JavaScript using either UglifyJS (default) or Closure Compiler.
I needed to do the same thing and this is how I solved it.
If you read the documentation about how to create custom builds (http://dojotoolkit.org/documentation/tutorials/1.8/build/), in the Layers section they talk about creating custom layers. You can add all the modules you need there. Here is an example of my custom layer file:
layers : {
"dojo/dojo" : {
include : [
"dojo/dojo",
"dojo/_base/window",//
"dojo/dom",//
"dojo/dom-class",//
"dojo/ready",//
"dojo/store/Memory"
],
customBase : true,
boot : true
}
}
What this will do is build only those modules into dojo.js, along with the bootstrap loader so that you can load other modules on the fly.
after optimizing a require.js project (pushing everything into one "big" .js file), is there any way to circumstance the need to include the require.js file (which then only loads one single .js file) and load the compiled file directly instead?
You can use a light weight AMD loader like Almond. You will still need a loader anyway as your compiled JavaScript still use define and require.