Is it possible to get grunt-usemin to only make html changes? - grunt-usemin

I am currently involved in a project where I am using require js.
In my gruntfile I am using requirejs to produce a single optimised js file.
I want to create a single css file to go with that and I want to use grunt-usemin for this.
My problem is that usemin doesn't seem to want to transform javascript import statements in my index.html without attemting to transform the javascript as well.
<script src="bower_components/requirejs/require.js" data-main="app/main.js"></script>
I desperately want usemin to change this to:
<script src="main.js"></script>
,but not make any changes to the javascript.
Is this possible? Right now useminPrepare stop at my script import with the error "require.js blocks are no more supported."
I tried configuring an 'empty' flow for useminPrepare ('flow': {'html': {'steps': {'js': []}}}) but this sadly didn't work.
If these tasks are impossible to combine for usemin, than suggestions for other grunt plugins i could use instead (or in addition) would be appreciated.

I decided to avoid the problems with usemin and started using grunt-regex-replace to change the script import.
Gruntfile.coffee:
'regex-replace':
html:
src: ['<%= settings.tempDirectory %>/index.html']
actions:[
search: '<script src="bower_components/requirejs/require.js" data-main="app/main"></script>'
replace: '<script src="main"></script>'
]

Related

”//…” in <script> tag is interpreted as “file://” in electron

I'm trying to include external AddThis widget in Electron.
<script type="text/javascript" src="//s7.addthis.com/js/300/addthis_widget.js#pubid=ra-xxxxxxxxxxxxxx"></script>
The issue is that
// in <script> tag is interpreted as file://.
And the app errors with
GET file://s7.addthis.com/js/300/addthis_widget.js#pubid=ra-xxxxxxxxxxxxxx net::ERR_FILE_NOT_FOUND
This can be easily fixed by adding http(s): before //. But huge mess happens if included js includes js'es starting with //. For example, addthis_widget.js includes 36 relative URLs starting with //
Such behavior takes place, because base URL in electron started with file: when application loaded: mainWindow.loadUrl('file:///index.html'). Then the relative URLs starting with // automatically resolved to file: and not http(s): But its not very clear how to revert things back.
Kindly help.
Adding js directly to the app is not an option, since AddThis modifying remote script(s) too often.

grunt concat js / css

I have created a web site using backbone + requirejs + bootstrap on client side and php REST on server side. The site contains a lot of .js file. I use requirejs to load the .js when it is needed (to implement asynchronous loading).
However, I have start using Node.js + Yeoman + grunt + bower recently. I use Yeoman webapp generator to create the basic structure of my web again. When I build my web, it concat all the .js files into 1 single .js file and put the tag on the index.html to refer it.
From my understand the pros is that the whole .js is cached in client's browser. which is slow at first time visit, but fast on re-visit. Since everything is concat to 1 file and it is loaded to the client's browser, so I guess the asynchronous loading is not work in this case. (correct me if I wrong).
* the web site is created for both mobile and desktop. (1 src for 2 version)
Should I concat all .js files in 1 single file
OR should I use requirejs to require the .js when I need it (Asynchronous loading)?
How to config requirejs in Node. I have tried it in normal way (include the data-main in index.html, when I compile using grunt build. it give me error "... is no more support".
Is browserify similar to requirejs in Node?
I have spent a week to figure it out already but still no luck. Hope someone can point me to the right direction. Thanks a lot.
The .js file structure is something like this:
-app
-vendor
-jquery.js
-backbone.js
-assets
-js
-model
-person.js
-collection
-people.js
-router.js
-controller.js
-dist
-js
-build.js
i had familiar issues. So lets start with strategy of file concatenation. There are three major ways to follow:
first - always concat all modules in one file, in this case you loose on first start and may win or next starts, but you can face another issue - you use less then half of modules from concatenated file at a time, but always load all modules.
second way is to build specific concatenated file with specific module set for each type of page - so you know how many page type you have and build file for each - following this you can decrease size of file, but its hardly to maintain and need manual sets correction in case of page changes.
third - build 1 concatenated file with libs and modules which in use nearly on all pages, all other stuff (additional modules, views, special models and collection) load on demand. This way is good in case of SPA pages.
Let me say a few words about grunt + r.js configauration.
Keep this link for first times .
Here is the sample of config:
requirejs: {
compile: {
options: {
baseUrl: "path/to/base",
mainConfigFile: "path/to/config.js",
name: "path/to/almond",
out: "path/to/optimized.js"
}
}
}
Main point here mainConfigFile - it is a file then you keep require.config
Next step - configure r.js - keep this link its very helpfull as describe all possibilities of r.js.
Usually its quite enough to checkout these links.
Also you can checkout recommend file structure for multi page site to avoid issues in future.
Also here is a link to a similar post - you may find it usefull.
If you have any additional questions let me know.
And a few words about CSS - logic nearlly the same : you can build separate file for each page or create sinngle. The main point here is how large your site is. In my case i've choose second option, but to be honest first one is more scalable, especially in large projects
I can get the requirejs work with Backbone now. However, I cannot use Marionette with error something like "Backbone is undefined". I've install Marionette with this command "bower install marionette --save". I did some search on google, and someone said use the AMD version of Marionette should fix this issue and after replace Marionette with AMD version it is work.
But my question is how can I install the AMD version of Marionette using "bower install"?
My web use bootstrap. When I compile the web with "grunt build". it copy bootstrap's font from "app/bower_components/bootstrap/dist/fonts" to "dist/bower_components/bootstrap/dist/fonts" but the web is refer the font on "dist/fonts". How can I change it to refer to the right directory?
I use yo webapp (with bootstrap) to generate the structure of my web.

NodeJS: Jade, Coffee, Scss assets rendered without writing to disk

I'm looking for some middleware modules that allow me to render ".css" from ".scss", ".html" from ".jade", ".js" from ".coffee" on the fly without rendering to disk.
Every module I've encountered so far wants to write to disk before serving it instead of just streaming it.
Obviously this is only for local development since I'm not interested in dealing with file-revving and caching problems.
Answering my own question here:
The middleware to use is compile-middleware. Works fine by default with connect, but with express I had to modify it in order to not write headers (ugly i know, but time waits for no one) : https://github.com/airtonix/compile-middleware
implementation:
https://gist.github.com/airtonix/9601224
Original Credit goes to (You should try using this one first):
https://github.com/shinohane/compile-middleware
You should simply use a JavaScript task runner like:
Grunt: http://gruntjs.com/ or
Gulp: http://gulpjs.com/
These plugins could help you get started (gulp related):
https://www.npmjs.org/package/gulp-watch
https://www.npmjs.org/package/gulp-jade
https://www.npmjs.org/package/gulp-coffee
https://www.npmjs.org/package/gulp-sass
Here's a simple tutorial: http://www.codersgrid.com/2014/01/11/gulp-js-streaming-build-tool-beats-grunt-js/
I got nothing against grunt, both of them are awesome :)
Hope it helps!

Loading min.js files Generated by TypeScript with Require

I have a full aplication working with Typescript and RequireJs, it is working perfectly. I have now download WebEssentials and it is generating the minified script files. WebEssentials generates separated *.min.js files with the same name as the original script file.
How can I tell RequireJs to load my minified files instead of my original script files ?
Thanks in advance
You can use path config to override module paths. You can even fall back to non minified files:
requirejs.config({
enforceDefine: true,
paths: {
jquery: [
'lib/jquery.min',
'lib/jquery'
]
}
});
There may be a more general way to use min files that I don't know about!
You can create a simple customized version of require which will conditionally append '.min.js' to all module file requests that would normally just receive the '.js' appendage. Consider the following:
//Establish a new 'useMinified' boolean in your initial config.
require.config({ useMinified: true });
Then, edit the require.js library file and modify the 'nameToUrl' function as below:
//Join the path parts together, then figure out if baseUrl is needed.
url = syms.join('/');
//new statement
var extension = config.useMinified ? '.min.js' : '.js';
//customized statement
url += (ext || (/^data\:|\?/.test(url) || skipExt ? '' : extension));
url = (url.charAt(0) === '/' || url.match(/^[\w\+\.\-]+:/) ? '' : config.baseUrl) + url;
There isn't any magic to this. You have a few options though
Use the RequireJS optimizer to generate min files for you. Very configurable.
Use the --out compiler option to concatenate all your files into one and minify that
Create a script/batch file to copy your app somewhere else, rename all .min.js files to .js and overwrite the non-min'd ones. Or some other mix but you get the gist
Use the paths config like Steve mentioned. OK for small apps, less than ideal for large.
For the best performance you should look into the optimizer and determine if the single-script approach is the right decision or multiple smaller libraries is a better approach. I doubt that loading each .min.js file is the ideal solution for you.

require.js - runtime dynamic variables to build path

Is it possible to inject runtime information in to a require.js "data main" script and use to build paths? More explanation...
In my node.js app.js I dynamically find the path to the configured 'theme' like this:
var themePath = require('./conf/config.js').config.theme.full_path;
and later in the require.js data main script, I'd like to prepend this theme path when defining paths. So assuming I've set my requirejs data-main="xxx" and the following is the xxx file, I'd like to do something like the following:
require.config({
baseUrl: "/js/",
paths: {
"templates" : DYNAMIC_THEME_PATH + '/templates',
"views" : DYNAMIC_THEME_PATH + '/views'
}
});
I'm not sure 1. how I can "see" the themePath from within this require.js data main file, and 2. is this even possible?
EDIT - My solution
So the real challenge I was having was getting a runtime variable discovered on the server in to the require.js data main script. In node land, global doesn't correspond to the window on the client side (of course) because the javascript isn't in to the browser yet .. duh. So I don't see how you can get this discoverable in the client side script.
Ok, so what I WAS able to do was inject the discovered theme path in the ejs, then, dynamically load the data main script with that prepended like:
<script data-main="<%= theme_path %>/main" src="../js/libs/require-jquery.js"></script>
Of course this means I have to have the data main script in the theme directory which wasn't my initial plan; however, it does have the advantage that I can then use relative paths to load my path/to/templates path/to/views, etc. etc.
Lastly, I sort of hate when folks answer they're own questions .. so I'm going to leave this up in hopes that someone can either give me a better recommendation or better explain this and they can get the credit ;)

Resources