I'm beginning to evaluate javascript module tools like RequireJS for javascript modularization. This seems useful, especially during development, so I don't need to recompile all of the js files into mylib-<version>.js whenever I change one of the dependent files.
My app is distributed with both html and javascript files, and in production, I would like to use the compiled version of the javascript file.
So in development, my html file might look something like
<html>
<head>
<script data-main="scripts/main" src="scripts/require.js"></script>
</head>
</html>
But in production, I would expect it to look more like
<html>
<head>
<script src="mylib-1.0.js"></script>
</head>
</html>
I wouldn't think it production that there should be any need to reference requirejs if I am distributing a compiled file.
Is there a way to do this without having to manually change my html files before I distribute the app?
RequireJs has an optimization tool, which can help you to minify and concatenate your modules. It has a lot of options, and can be difficult to use, but it gets easier with a build tool like GruntJs or (especially) Yeoman, which uses GruntJs to build.
In both you can use the rjs task (which optimizes modules), but again Yeoman is a bit easier since it has generators which will configure it already for you:
// usemin handler should point to the file containing
// the usemin blocks to be parsed
'usemin-handler': {
html: 'index.html'
},
// rjs configuration. You don't necessarily need to specify the typical
// `path` configuration, the rjs task will parse these values from your
// main module, using http://requirejs.org/docs/optimization.html#mainConfigFile
//
// name / out / mainConfig file should be used. You can let it blank if
// you're using usemin-handler to parse rjs config from markup (default
// setup)
rjs: {
// no minification, is done by the min task
optimize: 'none',
baseUrl: './scripts',
wrap: true,
name: 'main'
},
In the index.html you just use a comment line to specify which js files should be minified/concatenated to which output file:
<!-- build:js scripts/amd-app.js -->
<script data-main="scripts/main" src="scripts/vendor/require.js"></script>
<!-- endbuild -->
In the example above, the modules will be concatenated to ONE file, named amd-app.js.
Edit:
This will be done by executing grunt from the command line. This will start a lot of useful tasks, which will build the project in a dist folder, but again this is highly adaptable.
The resulting index.html file (in dist) has only (if you want) one javascript file:
<script src="scripts/15964141.amd-app.js"></script>
My advice: use Yeoman to make life easier (at least for handling minification/concatenation).
First you have to compile your depency tree into one file using the r compiler. After that you can a striped down AMD loader like almond. At least you have to find a way to change the url in your index html.
Take a look at gruntjs which can automatize the whole thing, there a bunch task to like usemin that helps you with the process.
Related
I cannot come up with a working solution. I guess I should somehow be using html-webpack-inline-source-plugin or a combination of multiple entry points but this is too much for me to handle.
What I want to have is:
all my js files bundled together and injected (not inlined) into index.html [this works of course!]
one js file, which is not included in the bundle described above, inlined into index.html
the inlined js file has to go through the Webpack "transformation pipe" since that js file depends on the Webpack build step
Example of the file to be inlined:
const asset = "require('./assets/blob.json')";
fetch(asset).then(.......)
This file should first go through the Webpack transformation since what should actually be inlined is something like:
<script>
var asset = "/static/json/blob.md5hashofblobjson.json";
fetch(asset).then(.......)
</script>
So basically the file that is to be inlined depends on the Webpack build process and cannot be just read with the fs module and written directly into index.html by hand.
Also, the inlined JavaScript should not include any WebpackJSONP bundle loading code, just the pure JS. Below that inlined piece of JS should come the usual bundled scripts that are injected (not inlined).
How should I configure my build process? Thanks a mil!
I am using VS 2015 + ASP.net vnext + Angular 2 + Typescript + gulp.js. I have automated my scripts/**/*.ts files moving to the wwwroot/app folder. Now I want to do the same for my libraries like Angular 2. I want that a gulp process injects
angular.js inside index.html inside the <environment names="Development"> node;
angular.min.js inside index.html inside the <environment names="Production"> node.
Of course I want that this to happen for all my libs automatically, without having knowledge about a library:
<any>.min.js (production)
<any>.js (development)
The minification of any.js can be done by me.
Actually I would just have to regard all dependencies in package.json... but then I am lost.
Can my idea be done or does there maybe already exist a tool? Or should the workflow broken into more manual steps like I have to copy/paste a certain library?
Or is it possible to take the dependencies name and concat it with .js then search this file under the node_modules folder... (kind of hacky and not safe...)
UPDATE
Rephrase/Refine my question:
How can I automatically add my npm dependencies (not devDependencies) to the environment "Development" node when triggering a certain event like build/clear/etc...
There is a little tag helper for this, called asp-src-include.
Imagine the case where you have a handful of *.js files you want to include:
<script src="/app/app.js"></script>
<script src="/app/controller/controllerA.js"></script>
<script src="/app/controller/controllerB.js"></script>
<script src="/app/service/userservice.js"></script>
etc. You can include all of these with a single `ยด tag.
<script asp-src-include="~/app/**/*.js"></script>
So for Production/Development deployment your Razor markup may look like
<environment names="Development">
<script asp-src-include="~/app/**/*.js"></script>
</environment>
<environment names="Staging,Production">
<script asp-src-include="~/app/**/*.min.js"></script>
</environment>
For this you need the #addTagHelper "*, Microsoft.AspNet.Mvc.TagHelpers" (starting with RC1 or RC2 it's ' #addTagHelper *, Microsoft.AspNet.Mvc.TagHelpers' - without the double-quotes ) declaration in your *.cshtml files or inside your _Layout.cshtml.
edit
There is an module called gulp-npm-files that does something similar, it copies all *.js files into the target folders. You can see it's source on GitHub in case you want write your own module to extend the functionality.
But that may not be exactly what you want, as the folders often contain multiple files, for example angular2 (AngularJS 2.0) contains dozen of files (*.js and *.ts), but you're mostly only interested in the compiled/minified ones, found in angular2/bundles/* like angular2.js, angular2.min.js or angular.dev.js.
The package.json of the particular dependency provides no information on where to find this compiled files. So I guess, there's no way to automate this unless you want to copy all of the files to wwwroot which makes no sense in my eyes, especially if you want to use asp-src-include, as it makes no difference on what it includes, so you want to minimize the number of *.js files in your wwwroot folder.
I guess the best you can do is to manually copy the dependencies via gulp task and then use asp-src-include to automatically include them into your razor generated html files.
So your problem is that you want to inject the scripts automatically into your HTML, right? You can use the Wiredep module for that.
And for copying the assets to an other folder, there are many modules to copy or link files from one folder to another. Gulp-copy is the first one i could find.
I am using HTMLmin in my grunt.js workflow to minify my HTML.
I have a few files that also include PHP markup. For example:
link
HTMLmin doesn't parse this correctly, and instead throws an exception error:
Warning: [filename]
Parse Error: link
Aborted due to warnings.
Is there anyway to instruct HTMLmin to ignore PHP markup? I've looked through the docs but don't see any obvious answer.
The world of modern JS doesn't take into account running in a subdir or templates that go through any kind of server side manipulation. The trick would be to inject the PHP after grunt minifies with some kind of data-* attribute. I haven't developed a solution I'm fully happy with. But, you can try some grunt regex tasks to do something like this
<a data-phphref="<?= $templatePrefix;?>" data-phpclass="<?= $activeLink;?>" href="/foo/">Foo</a>
after custom grunt task
Foo
Or you can do full DOM manipulation, which would probably be the better long term choice.
Update
I guess there's a 3rd option, and that would be to do token replacement to make regex easier. You can watch your source template files in a directory like ui-src/ When a change happens, run a simple search/replace for tokens
Foo
Output to a template directory that PHP is configured to use. This should allow you to minify like
<!-- build:js {{templatePrefix}}scripts/plugins.js -->
<script type="application/javascript" src={{templatePrefix}}components/bootstrap/js/affix.js"></script>
<!-- endbuild -->
With a grunt task like:
"string-replace": {
template: {
files: { "./": "<%= yeoman.dist %>/*.html.php"},
options: {
replacements:[ {
pattern: /{{templatePrefix}}/,
replacement: "<?= $templatePrefix;?>"
}
]
}
},
A bonus would be to put the PHP code snippets into a JS config file so your PHP code isn't littered throughout your Gruntfile.js
2nd Update
The preferred way to do this is have grunt-usemin inject the PHP code during the build. The recently released usemin 2.3.0 has this ability with blockReplacements.
feature request: https://github.com/yeoman/grunt-usemin/pull/337
commit: https://github.com/yeoman/grunt-usemin/commit/83f6821a30020cbc9395d7257e0276cff142e219
Basically, you can't make grunt ignore PHP, but you can make it work with PHP.
I am using gruntjs and usemin task.
I added this to my html file:
<!-- build:js scripts/all.js -->
<script src="../../core/module.js"></script>
<script src="../../core/base/alerts/alert-item.js"></script>
<script src="../../core/base/alerts/alerts-list.js"></script>
<script src="../../core/base/base_model.js"></script>
<script src="../../core/base/cursor.js"></script>
<script src="../../core/...<another script>...."></script>
<script src="../../core/...<another script>...."></script>
<script src="../../core/...<another script>...."></script>
<script src="../../core/...<another script>...."></script>
<!-- endbuild -->
As you can see, all the scripts are located in ../../core How can I tell usemin to take first ../../core/module.js and then ../../core/**/* without mention each and every file?
Is this possible at all?
For grunt task configurations you can use globing patterns to build a file list dynamically.
Have a look at the two consecutive paragraphs on 'Globbing patterns' and 'Building the files object dynamically' in the gruntjs doc:
http://gruntjs.com/configuring-tasks#globbing-patterns
If you paste your usimin task configuration, it would be possible to help you building the right pattern
EDIT:
Based upon the comment and the fact you don't control all the code, an alternative to usemin would be to use a 'src' and 'dist' directory structure as demonstrated in the sample gruntfile to handle the bulk move/concat/uglify.
In the source HTML, reference the file that will be generated in your 'dist' directory by the grunt tasks.
Configure grunt-watch to copy, concat and uglify the files from 'src' upon a change.
When you need to test or upload to production, you can do it out of 'dist' without worrying about what scripts may have been added or changed in 'src'.
If you are just adding new files from the other project, you can create and call a 'build' task that does the same three tasks as grunt-watch does in #3.
If you poke around, you can find examples of this approach in several javascript frameworks that you can borrow and modify to your needs. This article might be useful.
Original:
Based upon this and your other question asked today, it sounds like usemin might not be the right tool for your need. Something like require.js would cut the number of script tags in your HTML but would shift the need to enumerate them to a different file/location...and your complaint seems to be with writing all of the scripts as a manifest/list in the code.
Grunt offers a way to handle files en masse, but that's best utilized when copying directories or doing other similar low-risk bulk work. Thus, you can find ways to get usemin to bulk load without logic, but I suggest it is generally bad practice to "load all the javascripts". ...but if that's what you want, I would ask you why a bulk concatenate and uglify isn't the answer.
The benefits of a manifest or explicitly listing the files become more visible as a project grows in size or complexity. An innocent mistake that adds/removes a file from the directory can cause confusion and the cause isn't instantly clear. Listing the files explicitly in the HTML would cause usemin to throw an error if one was missing in the directory and later, you can also audit the directory to see what is still lingering even though it is no longer used. Globbing them would not offer either of these benefits.
Without a manifest, things can be solved through judicious use of a VCS and a review of changes since the last commit...but that's not as easy or as fun as saying "Hey, script.js got deleted and that's causing usemin to barf so somebody owes me a beverage for replacing the file and getting the build working again!"
I'm using Grunt to compile jade templates to html, uglify/concat js and minimize/concat css.
During development I use the combination of connect and watch to serve my front-end and pick up changes automatically. In this I also use the 'source' js and css (and not the uglified/concatted/minified version).
Now when I generate the production html, js and css I wonder what the best solution is to change the inclusions of the *.min js and css.
To be more specific in my html I e.g. include:
a.css
b.css
c.css
a.js
b.js
for development this is fine, but when generating the production version I want:
common-min.css
common-min.js
Of course I don't want to change the Jade templates manually so I'm looking for a better approach, probably with the use of some Grunt plugin.
You can pass data into your template that indicates what environment you are in, and then switch what you're including based on that.
// In your route:
res.render("index", { env: "development" }); // maybe use NODE_ENV in here?
// Then in your jade template:
head
if env == 'development'
link(href="a.css", rel="stylesheet", type="text/css")
link(href="b.css", rel="stylesheet", type="text/css")
else
link(href="min.css", rel="stylesheet", type="text/css")
See the Jade docs, and search for "conditionals": http://jade-lang.com/reference
#Marcel
What you're looking for is a jade build block processor (or more commonly an HTML build block processor). Unfortunately, for jade there only appears to be a gulp plugin, and not one for grunt.
https://www.npmjs.com/package/gulp-processjade
This example may suit your needs.
// build:js app.min.js
script(src='app.js')
// /build
#Jakerella
For each version, a production build is typically run once. So it's more effective to use a build server, task manager, or dependency manager; and less effective to dynamically generate the production version of the HTML page within the server's request handler. Don't use env with res.render() - logic used to build a page for production isn't needed when the entire server is built for production. This production logic also makes the request handler less modular, because it's coupled to the HTML page. Only build servers (ones dedicated to builds) should incorporate build logic. And, while the dynamically generated pages can be cached to avoid the repeated computation in rendering the production version of the HTML page, that's memory overhead that could be avoided.