how to create multiple js files from index.html using grunt usemin - javascript

My index.html has split js files as follows:
<head>
....
<!-- build:js js/app1.min.js -->
<!-- js from lib -->
<script src="bower_components/angular/angular.min.js"></script>
<script src="bower_components/angular-route/angular-route.min.js"></script>
<!-- js of this app -->
<script src="js/app.js"></script>
<script src="js/services.js"></script>
<!-- external js -->
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?v=3.exp"></script>
<!-- endbuild -->
....
</head>
.....
<body>
...
<!-- build:js js/app2.min.js -->
<!-- js from lib -->
<script src="bower_components/jquery/dist/jquery.min.js"></script>
<!-- angular-animate provides search functionality -->
<!-- js of this app -->
<script src="js/filters.js"></script>
<script src="js/directives.js"></script>
<!-- endbuild -->
....
</body>
As you can see, I tried to use two sets of js files. The reason to split is performance. How to use usemin in this case. I tried with following:
'useminPrepare': {
'html': 'app/index.html'
},
'usemin': {
'html': ['dist/index.html']
},
However, there is no folder/file created. But in index.html, those two sections are replaced appropriately by app1.min.js and app2.min.js
Moreover, I do not understand one thing that all examples are using concat and uglify in combination of usemin. The files in index.html which are already *.min.js eg. files included in bower_components folder, what happens to them?

Unless you're heavily invested in grunt already, give gulp a look.
Below is a snippet from gulpfile.js. The gulp.src() functions take a list of files, then pipe them through transformations, ending with a list of files, which get's written to disk with gulp.dest().
This let's the first two blocks of code src, transform (minify,concat,etc), and write the js and css.
The last block of code src()'s the index.html, injects the filenames from the first two blocks, and writes the index.html to a build folder. I do consulting on gulp builds.
Here's how you'd do it in gulp:
// Vendor files are pre-minified. Get right versions.
// JS. Concat, and add revision if necessary
var srcJs = config.minify ? config.dashboard.vendorJsMin : config.dashboard.vendorJs;
var destJs = 'vendor' + (config.minify?'.min':'') + '.js';
var vendorJs = gulp.src(srcJs)
.pipe(plugins.if(config.concat, plugins.concat(destJs)))
.pipe(plugins.if(config.hash, plugins.hash()))
.pipe(gulp.dest(config.dashboard.dest + '/js'))
// Vendor files are pre-minified. Get right versions.
// CSS. Concat, and add revision if necessary
var srcCss = config.minify ? config.dashboard.vendorCssMin : config.dashboard.vendorCss;
var destCss = 'vendor' + (config.minify?'.min':'') + '.css';
var vendorCss = gulp.src(srcCss)
.pipe(plugins.if(config.concat, plugins.concat(destCss)))
.pipe(plugins.if(config.hash, plugins.hash()))
.pipe(gulp.dest(config.dashboard.dest + '/css'))
// Inject all these files into index.html
return gulp.src(config.dashboard.index)
.pipe(plugins.plumber())
.pipe(plugins.inject(vendorJs, _.merge({name: 'vendor'}, config.dashboard.injectOptions)))
.pipe(plugins.inject(vendorCss, _.merge({name: 'vendor'}, config.dashboard.injectOptions)))
.pipe(plugins.inject(appJs, _.merge({name: 'app'}, config.dashboard.injectOptions)))
.pipe(plugins.inject(appCss, _.merge({name: 'app'}, config.dashboard.injectOptions)))
.pipe(plugins.inject(templates, _.merge({name: 'templates'}, config.dashboard.injectOptions)))
.pipe(plugins.replace('REPLACE_NODE_ENV', config.NODE_ENV))
.pipe(gulp.dest(config.dashboard.dest))
This is a much more 'dev' like build system than grunt. Grunt is much more 'ops' like. Whatever works best is the one to use!

Related

How to keep an absolute path unchanged for a script tag in index.html with Vite

With Vite, using absolute paths in index.html results in them being transformed based on the base config, which is nice.
For instance my index.html contains this:
<script type="text/javascript" src="/config.js"></script>
And base is set to "/demo". The exported index.html will contain:
<script type="text/javascript" src="/demo/config.js"></script>
This is fine for most of my file but I would need to have a script loaded from the root of the server for a very specific thing. Is it possible to indicate to Vite to not change the path of a specific script tag? Like a preprocessor command? Like this:
<!-- #vite-ignore -->
<script type="text/javascript" src="/config.js"></script>
That would be nice!
I used an ugly fix:
<script type="text/javascript">
// We have to do it using javascript otherwise Vite modifies the path
var config = document.createElement('script')
config.type = 'text/javascript'
config.src = '/config.js'
document.head.appendChild(config)
</script>

Webpack: require.ensure and extra vendor bundle

My website has two kind of pages:
Pages where javascript widgets are the main content of the page (TypeA) and where widgets are some additional content, that user might to trigger (TypeB).
So I'd like to split my JS codebase into three bundles:
vendor.js -- which is included on all pages
runtime.js -- for widgets
specific entry points for different pages
For TypeA-pages I have this:
<script src="vendor.js"></script>
<script src="runtime.js"></script>
<script src="pageA.js"></script>
<!-- pageA.js launches the widget -->
But for TypeB I want this:
<script src="vendor.js"></script>
<scriprt>
<!-- pseudo code -->
when('user clicks button', function() {
require.ensure('pageB.js', function(require) {
var pageBCode = require('pageB.js');
<!-- do the magic -->
<!-- but I also need runtime.js here -->
});
});
</script>
The problem is, that I want to reuse runtime.js in both sync and async pages. But I can't figure out how to load runtime.js along with my on-demand loading pageB.js. I still have to include it via <script src="runtime.js"></script>.
(I use CommonChunksPlugin for creating vendor.js and runtime.js, and it works well on TypeA pages)
You can pass an array to require.ensure as such:
require.ensure(['pageB.js','runtime.js'], function(require){
var pageBCode = require('pageB.js'),
runtimeCode = require('runtime.js');
/** MAGIC! **/
});

Angular2 require is not defined for libraries in node_modules

I am using angular2-seed as a seed for my project. The require is working perfectly fine in source files. But whenever I include a new library and reference it in index.html, there pops ups an error in console that require is not defined.
Systemjs is included
I have READ previous answers on SO which suggests to use system.js. The systemjs is already included.
Index.html
<!-- shims:js -->
<script src="/node_modules/systemjs/dist/system.src.js?1458283463580"></script>
<script src="/node_modules/systemjs/dist/system-polyfills.src.js?1458283463581"></script>
<script src="/node_modules/reflect-metadata/Reflect.js?1458283463582"></script>
<script src="/node_modules/es6-shim/es6-shim.js?1458283463582"></script>
<script src="/node_modules/angular2/bundles/angular2-polyfills.js?1458283463582"></script>
<!-- endinject -->
<script>System.config({"defaultJSExtensions":true,"paths":{"./admin/main":"/./admin/main","angular2/*":"/angular2/*","rxjs/*":"/rxjs/*","*":"/node_modules/*"},"packages":{"angular2":{"defaultExtension":false},"rxjs":{"defaultExtension":false}},"map":{"moment":"moment/moment.js"}})</script>
<!-- libs:js -->
<script src="/node_modules/rxjs/bundles/Rx.js?1458283463585"></script>
<script src="/node_modules/angular2/bundles/angular2.js?1458283463585"></script>
<script src="/node_modules/angular2/bundles/router.js?1458283463585"></script>
<script src="/node_modules/angular2/bundles/http.js?1458283463586"></script>
<script src="/node_modules/ng2-bootstrap/ng2-bootstrap.js?1458283463586"></script>
<script src="/node_modules/ng2-select/ng2-select.js?1458283463586"></script>
<script src="/node_modules/lodash/index.js?1458283463587"></script>
<script src="/node_modules/ng2-pagination/index.js?1458283463587"></script>
<!-- endinject -->
<!-- inject:js -->
<!-- endinject -->
<script>
System.import('./admin/main')
.catch(function (e) {
console.error(e,
'Report this error at https://github.com/punchagency/staffing-client/issues');
});
</script>
Error
Source where require is used
index.js of lodash
module.exports = require('./lodash');
Similarly other libraries like ng2-select and ng2-bootstrap have similar errors
You need to configure your additional dependencies in SystemJS and not include them directly into script tag.
Here is a sample:
<script>
System.configure({
map: {
'ng2-bootstrap': 'node_modules/ng2-bootstrap',
'ng2-select': 'node_modules/ng2-select',
lodash: 'node_modules/lodash/lodash.js'
},
package: {
(...)
}
});
System.import(...);
</script>
See these questions for more details:
integrate bootstrap module and ng2-select module to angular2 5min quickstart
angular2 failing lodash import

Writing jQuery in separte files to support concatenation in production

For now I have written my .js files as followed because I think, this is simple for maintenance.
//main.js
$(function() {
//declare variables, functions
});
//page1.js
$(function() {
//whatever for page1
});
//page2.js
$(function() {
//whatever for page2
});
In .html I just have to specify which .js files to load, this is working so far because the individual .html is assigned with the right .js files
<!-- page1.html -->
<script src="main.js">
<script src="page1.js">
<!-- page2.html -->
<script src="main.js">
<script src="page2.js">
If I plan to concatenate all .js files into one single .js file for production purpose, how should i restructure my .js files to support concatenation so in each .html i can only use <script src="all.js">
Please guide what to do.
Thanks.

usemin using wrong directory for input asset files

I'm attempting to get a gruntfile working to concatenate / uglify javascript files in a Laravel application. All of my tasks work in isolation, but for whatever reason the paths to my input javascript files are not being set correctly.
Here's an example of one of my blade templates:
#section('scripts')
<!-- build:js /js/min/page.min.js -->
<script type="text/javascript" src="/js/scrollIt.min.js"></script>
<script type="text/javascript" src="/js/jquery.omniwindow.js"></script>
<script type="text/javascript" src="/js/isotope.min.js"></script>
<!-- endbuild -->
#stop
Here's my useminPrepare / usemin task definitions:
useminPrepare: {
html: 'app/views/**/*.blade.php',
options: {
dest: 'app/views/dist'
}
},
usemin: {
options: {
assetDirs: [ 'public/js' ]
},
html: [ 'app/views/dist/**/*.blade.php' ]
},
I have no defined uglify task, I'm just relying on the one that usemin will generate.
All templates are making it into the 'app/views/dist' directory correctly, with the correct replacement (in the example above, there's a single javascript file at public/js/min/page.min.js being included in the template). During processing, I noticed output:
$ grunt build
Running "useminPrepare:html" (useminPrepare) task
Going through {list of templates} to update the config
Looking for build script HTML comment blocks
Configuration is now:
concat:
{ generated:
{ files:
[ { dest: '.tmp/concat/js/min/page.min.js',
src:
[ 'app/views/course/js/scrollIt.min.js',
'app/views/course/js/jquery.omniwindow.js',
'app/views/course/js/isotope.min.js' ] },
] } }
uglify:
{ generated:
{ files:
[ { dest: 'app/views/dist/js/min/page.min.js',
src: [ '.tmp/concat/js/min/page.min.js' ] },
] } }
cssmin:
{}
As you can see above, it is looking for my javascript files in app/views/course/js directory, which is incorrect. Why is this? I thought specifying assetDirs: ['public/js'] in my usemin task would tell grunt where to find those files. I have tried changing the script references to look like this:
<script type="text/javascript" src="../../../public/js/scrollIt.min.js"></script>
And this causes a successful build, but breaks my local development so its definitely not a solution. Do I need to somehow override the uglify:generated task, and if so, how do I do it for multiple different templates with generated filenames?
If it's necessary, you can see the entirety of my Gruntfile.js here. You can see from there I had to also add a new copy task for copying Javascript files from app/views/dist/js/min back over to public/js/min. I'd also like to get rid of that, but if I can just get around this issue I'd be happy.
The answer here actually turned out to be relatively simple, and was able to be gathered directly from the usemin documentation (as soon as I started to look hard enough):
Blocks are expressed as:
<!-- build:<type>(alternate search path) <path> -->
... HTML Markup, list of script / link tags.
<!-- endbuild -->
In my case for working with Laravel, I needed to specify an alternate search path of public/ and it wound up working just fine:
#section('scripts')
<!-- build:js(public/) /js/min/script.min.js -->
<script type="text/javascript" src="/js/script1.js"></script>
<script type="text/javascript" src="/js/script2.js"></script>
<script type="text/javascript" src="/js/script3.js"></script>
<script type="text/javascript" src="/js/script4.js"></script>
<!-- endbuid -->
#stop

Categories

Resources