Grunt Uglify - make specific file last - javascript

How do I setup my gruntfile.js to have a specific file be the last file included in uglify. For example, I have an autoloader.js file that I want to be the last file included in uglify. I have many other .js files so I'm dynamically combining all files in the directory.
I know if there's a file I want included first - I list it first eg:
files: {
'Scripts/application.js': [
'bower_components/moment/moment.js',
'Scripts/assets/defaults.js',
'Scripts/assets/api.js',
'Scripts/assets/**/*.js'
]
}
I want to keep the dynamic grabbing of all files as we add new files regularly. But I need my autoloader.js to be last.
I'm hoping there's a better way than renaming it to zAutoLoader.js
NOTE: The following does NOT work
files: {
'Scripts/application.js': [
'bower_components/moment/moment.js',
'Scripts/assets/defaults.js',
'Scripts/assets/api.js',
'Scripts/assets/**/*.js',
'Scripts/assets/autoloader.js
]
}
nor does
files: {
'Scripts/application.js': [
'bower_components/moment/moment.js',
'Scripts/assets/defaults.js',
'Scripts/assets/api.js',
'Scripts/assets/**/*.js',
!'Scripts/assets/autoloader.js'
'Scripts/assets/autoloader.js'
]
}

Related

Webpack to simply compile a bunch of Pug templates to HTML

Im getting started with webpack but one thing I cannot for the life of me work out is how to take a folder (with possible nested folders), full of .pug templates, and simply compile them to static html and put them in the output folder, maintaining any nested folder structure for each output html file that was in the source templates folder...
I dont want to have to manually specify each individual .pug file, and I definitely dont want webpack to try and parse the .pugs into JS and then attempt to require/import any of the imgs/fonts etc in the pug files and then complain about it, Im just after a basic, static 1:1 compile, pug file in, html file out. Why is it so hard to do that?
Use pug-html-loader to convert .pug to .html file. Use file-loader to copy the file to desired location. Don't use html-loader as you don't want to process resources used by the generated file.
You will end up something like this in your loader rules (untested, webpack 1 syntax, you may need to tweak it for webpack 2)
{
test: /\.pug$/,
loaders: ['file-loader?name=[path][name].html', 'pug-html-loader?pretty&exports=false']
}
Next you need to require all your pug files in your entry file
function requireAll (r) { r.keys().forEach(r); }
requireAll(require.context('./', true, /\.pug$/));
This can be done very simply with only html-webpack-plugin and pug-loader.
webpack.config.js
const HTMLWebpackPlugin = require('html-webpack-plugin');
module.exports = {
// No javascript entrypoint to evaluate. Let the plugin do the heavy lifting
entry: {},
// Translate Pug to HTML
module: { rules: [ { test: /\.pug$/, use: 'pug-loader' } ] },
// Save HTML to file
plugins: [ new HTMLWebpackPlugin({ template: './src/index.pug' }) ]
};
./src/index.pug
doctype html
html(land="en")
head
include path/to/another.pug
...
Got this information from https://extri.co/2017/05/23/using-htmlwebpackplugin-and-pug/ and you can also go further to import css and javascript as normally done with html-webpack-plugin.

How to make couple of minified files from different js files using grunt

I am new to grunt and task runners in JS, so this might seem a simple question but I have been unable to find exact working answer.
I have :
concat: {
options: {
// define a string to put between each file in the concatenated output
separator: '\n\n'
},
dist: {
// the files to concatenate
src: ['scripts/app.js', 'scripts/constant.js'
],
// the location of the resulting JS file
dest: 'scripts/custom.js'
}
},
This task collects all my custom file together. What I want is to do similar thing for all my vendors file. Finally I should end up with two js only custom.js having my concatenated-minified code and vendor.js having concatenated-minfied libraries.
How do I write grunt configuration for this. Do I need to make two different tasks. If I write the above code twice with different input files, it seems to run the last code.
grunt-contrib-concat can be configured to utilize multiple-targets.
For further documentation on this subject refer to multi-tasks and Task Configuration and Targets in the grunt documentation.
Gruntfile.js
For your scenario you need to configure your concat task similar to this (Note: the new custom and vendor targets):
module.exports = function(grunt) {
grunt.initConfig({
concat: {
options: {
separator: '\n\n'
},
custom: {
src: ['scripts/app.js', 'scripts/constant.js'],
dest: 'scripts/output/custom.js'
},
vendor: {
// Modify the src and dest paths as required...
src: ['scripts/vendor/foo.js', 'scripts/vendor/baz.js'],
dest: 'scripts/output/vendor.js'
}
}
});
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.registerTask('concatenate', [
'concat:custom', // <-- Targets in a task are called using a colon separator.
'concat:vendor'
]);
};
Running concat
Using the example gist provided above you can run the concat task via the CLI by typing the following command:
$ grunt concatenate
Configuring Options
If you require different configuration options for both the custom and vendor targets you will need to move the options object inside their respective targets. As explained here.
Note: Using the example gist provided the options specified will apply to both targets.

Dynamically load chunks in webpack?

We load files dynamically i.e., we don't know which files will be loaded until runtime. At the same, for faster loading, we'd like to put related files in the same chunk.
How can I do that with webpack?
This is what we have and it's failing with a 404 error (1.1.bundle.js not found)
This is what webpack.config looks like:
entry: {
main: //...,
related_files: [ //should create chunk for file1 and file2?
'./file1.js',
'./file2.js'
]
},
This is what the code to dynamically load the files looks like:
var dynamicFileName = //...
require.ensure([], function (require) {
//should dynamically load the chunk containing dynamicFileName?
//fails with 'file1.js' or 'file2.js'
var modImpl = require(dynamicFileName);
//...
});
Update 1: the error message is caused by not configuring output.publicPath. However, I never created 1.1.bundle.js. It seems to be ignoring the entry point.
Update 2: even after fixing output.publicPath, it's unable to load a dynamically generated filename. So it seems that webpack cannot handle this.
By default, webpack tries to bundle all the code in a single file. If you're using code from file1.js/file2.js in main entry point, webpack will bundle contents of all the files in main.js, and second entry point related_files will output only file1/file2 contents.
Webpack handles this situation by using CommonsChunkPlugin, your config must look like this:
entry: {
main: //...,
related_files: ['./file1.js','./file2.js']
},
plugins: [
new webpack.optimize.CommonsChunkPlugin('related_files', 'related_files.js')
]
Second part of the question is that webpack parses require statement, and outputs 1.1.bundle.js - the dynamic module, that can be loaded with require in the code. In your case, dynamicFileName = 'related_files', not file1/file2.
Please see http://webpack.github.io/docs/code-splitting.html#split-app-and-vendor-code

Grunt + Concat + Angularjs

Setup:
A Gruntfile with the following task:
concat: {
build: {
files: {
'build/app.js': [
'src/.js',
'src//.js',
'!src/vendors/'
],
}
}
A lot of angular modules, with its controllers, services, and so on, with a structure like this:
a/
a.js // Module declaration like: angular.module('a',[])
a-controller.ks // Which sets a controller in its root module definition like: angular.module('a').controller()...
Issue:
The task concatenates all the js files it finds in the build folder to a single app.js file, and it does this fine, but messes up with the order of files when concatenating.
For instance, it concatenates first the controller file instead of the main folder file containing the module declaration, triggering the following error:
Module xxxx not available!
I suppose the issue lies in the way concat builds up the files and that is done by the grunt core and specifically the minimatch library, and the possibility it treats dashes to be first than letters, but I don't know how configure to change that behavior, and even know if that is possible.
Question:
So, the question is: How can I make Grunt/Grunt-concat to process dashed f first than the others in the same folder so the ordering is maintained?
Thanks
Update 1:
After digging more, It seems that it has nothing to do with the ordering inside a folder, but Grunt/Core sending the root files to the end and putting them the leaf ones first.
Just specify the order you want to concat your files, placing them in order, what I mean is, first add your single files that should be concatenated at start, after your full folder that does not need to have an order, and finally your final files, something rougth like this:
grunt.initConfig({
concat: {
js: {
src: ['lib/before.js', 'lib/*', 'lib/after.js'],
dest: 'bundle.js',
}
}
});
You will have to specify to the grunt-concat task the order you want your files built. For my projects, I typically keep a folder structure where controllers go in a app/controllers folder, services in services, and etc, but names can vary. I also keep an app.js that declares my app module and specifies the config handler for it. I use a config like this for grunt-uglify but the same can be done for concat with little to no changes:
uglify: {
development: {
files: {
'public/scripts/app.js': [
'public/app/app.js',
'public/app/controllers/*.js',
'public/app/directives/*.js',
'public/app/services/*.js'
]
}
}
}
I just copy paste my answer, the detail you want on second picture, i hope help you.
you may consider this solution
Separate the module declaration to xxx.module.js
In grunt-contrib-concat modify the config like below :
place this outside grunt.initConfig
var clientApp = './app/';
grunt-contrib-concat config
dist: {// grab module first, state the second
src: [
clientApp+'**/*-controller.js',
clientApp+'**/*.module.js',
clientApp+'**/*.state.js',
clientApp+'**/*.js'
],
dest: 'dist/<%= pkg.name %>.js'
}
i use state to so i have to define state too before trying to navigate to any state. This is preview my code, the module declaration is declared fist before anything, then my state. even minified doesnt create any problem.
I hope this help you.
i follow this johnpapa's style guide, your problem might solve there if my solution not work

Dynamically add version number to dest output files w/ grunt

I have a package.json file with our version number, such as:
{
name: "myproject"
version: "2.0"
}
My goal is to dynamically add the version number from the package.json file into the output files. For example, in the javascript I don't want to manually update the version number, but would like something similar to this to be generated after each grunt build:
/* My Project, v2.0 */
window.myProject = {
version: "2.0"
};
Is there an easy way to do this in my Gruntfile.js configuration?
I implemented: https://github.com/erickrdch/grunt-string-replace
In my source css/js files, I use the text {{ VERSION }} which gets replaced with the version number set in the package.json file. Below is the config I added to Gruntfile.js.
'string-replace': {
version: {
files: {
// the files I did string replacement on
},
options: {
replacements: [{
pattern: /{{ VERSION }}/g,
replacement: '<%= pkg.version %>'
}]
}
}
},
pkg: grunt.file.readJSON('package.json'),
I think that what you only want to do is to put some kind of trick for unable the page to use the cache files that maybe the browser have, and by now, the only way for that cross-browser is putting something on the href urls like "app.v2_2.js" or "app.js?ver=22". So I use this grunt npm package:
https://www.npmjs.org/package/grunt-cache-breaker
By default it only adds a parameter to your javascript and in almost the cases is the thing you need for not using cache, but you can configure even if you change the name of the file in other grunt process. This only change the HTML headers to what you desire.
After you install the grunt-cache-breaker, add this to your GruntFile:
// Append a timestamp to 'app.js', 'controllers.min.js' which are both located in 'index.html'
// resulting in the index the call of : href="~/app.js?rel=1415124174159"...
cachebreaker: {
dev: {
options: {
match: ['app.js', 'styles.css']
},
files: {
src: ['dist/index.html']
}
}
},
Then where you load the modules:
grunt.loadNpmTasks('grunt-cache-breaker');
Add on the task you want to:
grunt.registerTask('deploy', [
'clean:app',
'copy:views',
'copy:imgs',
'copy:css',
'uglify:app',
'cssmin:app',
'cachebreaker:dev'
]);
And finally run the grunt action on the console/command prompt
> grunt deploy
I would suggest using the banner feature in grunt-contrib-concat
this can be done as well with the banner option of https://github.com/gruntjs/grunt-contrib-uglify - which takes also care of the minifiaction of the javascript files.
filerev provides this option now. Use process to manipulate the filename that will be otherwise suffixed with md5 hash of the file content. You can use this to insert your version to every file you want.
Ref: https://github.com/yeoman/grunt-filerev
create something like package.json in the root of your project
it should read that or you can do something like
pkg: grunt.file.readJSON('package.json'),
in that you'll have a version declaration which would obviously correspond to <%= pkg.version %> so have that string in your json output and then run grunt.config.process to do the variable replacement
do something similar for the comment header

Categories

Resources