How to used compiled requirejs layer instead of require.js? - javascript

I have quite a basic question, that unfortunately I can't find answer for in tutorials.
My entry point to require.js is js/main.js. I've configured build.js :
({
baseUrl: "js",
paths: {
// bower dependencies go here
},
name: "main",
out: "dist/main.min.js"
})
added build to package.json:
"build": "bower install --allow-root && node node_modules/requirejs/bin/r.js -o build.js"
and got my minified layer, which seems to include all my js files.
However, the information that fails is what to do with that layer afterwards.
When I've added:
<script src="dist/main.min.js" type="text/javascript"></script>
to my index.html before
<script data-main="js/main" src="bower_components/requirejs/require.js"></script>
the whole js files are loaded one by one by require.js. When I remove require.js, nothing happens (the code from the compiled layer doesn't call the app initialization routine).
What I'm missing here?

It looks like the answer is as trivial as replacing js/main layer declaration with dist/main.min:
<script data-main="dist/main.min" src="bower_components/requirejs/require.js"></script>
or even better, simply overwriting js/main with minimized layer in build script when preparing distribution directory.
Thanks to https://stackoverflow.com/a/20004336/5479362
Honestly, I don't understand why that information is missing from requireJs tutorial...

Related

How do you use bundles in your code when you browserify an npm module?

I want to use a javascript library called fuse.js. (https://fusejs.io/) in my vanilla javascript app.
I npm install fuse and then add
const Fuse = require('fuse.js')
...other javascript functions here
to the top of my script.js file. (i have trie removing the .js but the lib is called fuse.js in the node_modules folder)
I then run:
browserify script.js -o bundle.js
then I add the bundle.js to my index.html
<script type="module" src="bundle.js"></script>
then, no matter what I do I can't access the Fuse object or any of my other javascript functions...It does load the bundle...but it's completely "closed", I can't use any functions in it.
I have seen that the guys export the bundle to the window object, but there are a lot of people saying this isn't best practice?
Are there any good resources anyone can recommend that I can study up to understand the concept of
I see a useful library on npm, and I use it in my front-end code
(fuse.js does have a cdn that I can just include in the script tag, but I want to know for future use how to use npm modules in my front-end workflow?)

Integrating Sails Js with Angular 2

I'm trying to integrate Angular 2 in a Sails Js application. I'm new to both. I have been following this official tutorial here. It works fine in standalone mode with a static http server but when i try to integrate into sails app i get following problems:
1 - How do i refer to angular2 js inside the local node_modules folder. Everytime i do, sails interprets it as a route and gives me a 404 for my scripts. For instance:
<script src="node_modules/angular2/dist/angular2.min.js"></script>
I was able to overcome above issue using cdnjs links for now but i would like to know a better/proper solution.
2 - I added the tsc and tsc -w scripts to my package.json, but even with sails lift --verbose i do not get any output or error. Here is how I added the script to json file:
"scripts": {
"tsc": "tsc",
"tsc:w": "tsc -w",
"debug": "node debug app.js",
"start": "node app.js"
}
In the end i had to install typescript with -g and compile manually. That worked, but again, it's expected to work with the scripts. It would be great to know what I'm missing.
3 - After jumping through hoops to get rid of the above errors, when i lift the server again, it gives me more 404 error which seem to be coming from system.src.js and that I am unable to figure out. Please see the console screengrab below.
I think I might be making a mistake setting up the angular application directories within sails. Just to make sure we cover everything, here is the directory structure I'm using. The sails app does not have anything in it yet. Which is why the below paths are just for angular related artifacts and assets.
Within the assets folder:
app
│   ├── app.component.ts
│   └── main.ts
Of course the .ts files get compiled to js.
In the sails views folder I have layout.ejs which has following contents:
.
.
.
<script src="https://cdnjs.cloudflare.com/ajax/libs/es6-shim/0.34.2/es6-shim.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.17/system-polyfills.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/2.0.0-beta.1/angular2-polyfills.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.17/system.src.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/4.0.7/rx.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/2.0.0-beta.1/angular2.dev.js"></script>
<script>
System.config({
packages: {
app: {
format: 'register',
defaultExtension: 'js'
}
}
});
System.import('/app/main')
.then(null, console.error.bind(console));
</script>
.
.
.
<my-app>Loading...</my-app>
In addition to above files, I have also added the tsconfig in the sails root folder.
I have followed the code and directory structure guidelines from the official quickstart tutorial.
So, for anyone interested, i have resolved the issues like so:
1 - For providing static access to node_modules i created an express middleware (probably use policies for this as well?):
(config/express.js)
var express = require('express');
module.exports.http = {
customMiddleware: function (app) {
app.use('/node_modules', express.static(process.cwd() + '/node_modules'));
}
};
2 - I was able to compile already so all good there
3 - For the rxjs related errors, i did some research and found out that rxjs is no longer bundled with angular 2. Therefor, i had to modify the systemjs config a bit to add mapping for rxjs, like so:
(views/layout.ejs)
System.config({
map: {
rxjs: 'node_modules/rxjs' // added this map section
},
packages: {
app: {
format: 'register',
defaultExtension: 'js'
},
'rxjs': {defaultExtension: 'js'} // and added this to packages
}
});
System.import('/app/main')
.then(null, console.error.bind(console));
You need to setup access to your static files. You can check out how, right here.
http://sailsjs.org/documentation/concepts/assets
So put those node modules into an asset folder, for which you can then have static access.
However, are you sure you want to do this with Sails? As far as I know Sails is a fullblown MVC framework, which you won't really need if you only want to use it as a backend for Angular. I'd recommend using something like Express instead.
You can use the JavaScript files that are provided in the folder node_modules/angular2/bundles:
<script src="node_modules/angular2/bundles/angular2-polyfills.js"></script>
<script src="node_modules/systemjs/dist/system.src.js"></script>
<script src="node_modules/rxjs/bundles/Rx.js"></script>
<script src="node_modules/angular2/bundles/angular2.dev.js"></script>
<script src="node_modules/angular2/bundles/router.dev.js"></script>
<script src="node_modules/angular2/bundles/http.dev.js"></script>
This should answer to your first question.
Regarding the second question, elements you put in the scripts block of your package.json file are aliases for commands. The tsc -w one waits for updates in TypeScript files and automatically compiles them. This command must be started in background... For example with: npm run tsc:w.
Hope it helps you,
Thierry
(1) For the first question:
The problem with 404 angular files not found is that when Sails lifts Grunt deletes all the files in .tmp then rebuilds the project from scratch, so what happens is Sails server starts before the build is finished and the files are not there that's why you get 404. If you wait for a little while your page should load without any errors.
If waiting get too long use these scripts from CDN:
<script src="https://rawgithub.com/systemjs/systemjs/0.19.6/dist/system.js"></script>
<script src="https://code.angularjs.org/tools/typescript.js"></script>
<script src="https://code.angularjs.org/2.0.0-beta.1/angular2-polyfills.js"></script>
<script src="https://code.angularjs.org/2.0.0-beta.1/Rx.js"></script>
<script src="https://code.angularjs.org/2.0.0-beta.1/angular2.dev.js"></script>
<script src="https://code.angularjs.org/2.0.0-beta.1/router.dev.js"></script>
<script src="https://code.angularjs.org/2.0.0-beta.1/http.dev.js"></script>
(2) Second question:
Run tsc in a separate console window like this:
npm run tsc:w
(3) The third problem by adding the following to components where it's needed:
import 'rxjs/add/operator/map';

how to use webpack to load CDN or external vendor javascript lib in js file, not in html file

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.

'define' is not defined error on RequireJS & Webapp Yo generator

I have struggled a few days to figure this out,, but finally I need your help today.
my repo: https://github.com/seoyoochan/bitsnut-web
what I want to achieve:
- Load and optimize r.js
- Write bower tasks for RequireJS and r.js :
tasks are: minify & uglify & concatenation for RequireJS, and optimise with r.js on production
- How to exclude js script tags in index.html when using wiredep tasks and load them through RequireJS loader?
I use Yeoman 'Webapp' generator and generated the scaffold app.
I installed backbone, marionette, text, underscore, and etc via bower install
I modified bower.json by removing dependencies and left only "requirejs": "~2.1.16" on dependencies. (devDependencies is empty)
because I use [2][grunt-wiredep], everything is automatically loaded bower_components into index.html.
I modified .bowerrc to store dependencies at app/scripts/vendor.
However, the problem is that I don't know how to successfully load them through ReuqireJS and not to load the vendors as script tags inside index.html.
I have to write some tasks for RequireJS and r.js, but don't know how to achieve this goal ( I installed grunt-contrib-requirejs though )
I want to follow the 4th method to make use of r.js at https://github.com/jrburke/requirejs/wiki/Patterns-for-separating-config-from-the-main-module. but the issue I encountered was that RequireJS's documentation does suggest to not use named module, but anonymous module.
I would like to hear various opinions about how I should approach.
I really appreciate your help in advance!
You load your scripts manually here and here, rendering the whole point of requireJS useless. You also load main first here config.js#L49.
Instead, you should only have this line in your index.html
<script data-main="scripts/config" src="scripts/vendor/requirejs/require.js"></script>
And load all your dependencies in that file (like you do with main) using define() and require(). As you have set exports, which sets the values as globals, the functions can be empty. Here's an sample:
define([
"jquery",
"underscore",
"backbone",
"marionette",
"modernizr"
], function () {
require([
"backbone.babysitter",
"backbone.wreqr",
"text",
"semantic"
], function () {
/* plugins ready */
});
define(["main"], function (App) {
App.start();
});
});
Also the baseUrl is the same as the directory as your data-main attributes folder (http://requirejs.org/docs/api.html#jsfiles):
RequireJS loads all code relative to a baseUrl. The baseUrl is
normally set to the same directory as the script used in a data-main
attribute for the top level script to load for a page. The data-main
attribute is a special attribute that require.js will check to start
script loading.
So I think your baseUrl in config.js points to scripts/scripts/-folder which doesn't exist. It could/should be vendor/ instead (and remove the vendor part from all of the declarations) or just left empty.
Instead of wiredep, you could try using https://github.com/yeoman/grunt-bower-requirejs which does similar things to wiredep but specially for bower/requirejs apps (see: https://github.com/stephenplusplus/grunt-wiredep/issues/7)
Your repo doens't include the dist-folder for jQuery, but otherwise here's a working sample of config.js: http://jsfiddle.net/petetnt/z6Levh6r/
As for the module-definition, it should be
require(["dependency1", "dependency2"])
and the module should return itself. Currently your main file sets itself as a dependency
require(["main", "backbone", "marionette"], function(App, Backbone, Marionette){
As you already set the backbone and marionette as globals with exports, you can again set the function attributes empty, so your main file should look like this:
require(["backbone", "marionette"], function(){
"use strict";
var App = new Backbone.Marionette.Application();
App.addInitializer(function(){
console.log("hello world!");
Backbone.history.start();
});
return App;
});
And as you already use define to load main, don't require it again. Instead just call App.start() inside the define function.
https://jsfiddle.net/66brptd2/ (config.js)

Can I combine RequireJs modules AND require.js itself into one js-bundle

I'm using RequireJs Optimizer to combine all modules into one file - app.js
On production I have two js files: app.js and require.js
Production HTML has following script tag:
<script data-main="app.js" src="require.js"></script>
This will result in two requests for js files when running.
The question: is it possible to combine everything including all modules and require.js itself into one file, so I have only one request when running?
The answer is here http://requirejs.org/docs/optimization.html#onejs
I had to include require.js through 'include' r.js option.
With gulp task and gulp-requirejs it looks like this:
requirejs({
paths: {
requireLib: 'lib/require'
},
include: ['requireLib'],
out: 'bundle.js'
})
.pipe(insert.append('require(["app"]);'))
Notice I had to append require(["app"]) to the end of js-bundle to start main module.
Now I can reference only 'bundle.js' on the page and have one request.
<script type="text/javascript" src="bundle.js"></script>
AlmondJS sounds like a good fit, snippets from their documentation:
A replacement AMD loader for RequireJS. It provides a minimal AMD API
footprint that includes loader plugin support. Only useful for
built/bundled AMD modules, does not do dynamic loading.
...
By including almond in the built file, there is no need for RequireJS.
almond is around 1 kilobyte when minified with Closure Compiler and
gzipped.
For example
node r.js -o baseUrl=. name=path/to/almond include=main out=main-built.js wrap=true
Will output something like this:
(function () {
//almond will be here
//main and its nested dependencies will be here
}());
Admittedly I've not used it, but I've heard of it.

Categories

Resources