Grunt Uglify files from list in external document - json

I have a module system, which can be controlled via an admin UI, developers can enable or disable features and the task runner then takes care of preparing all UI assets into single files to load on the front-end.
With SASS, I can programmatically control the index.scss file to be compiled, meaning that this is simple enough - however, with JS I don't find the same option, yet.
The idea is to avoid any file duplication, manipulation or movement, to reduce complexity, avoid issues and also to speed up the task runner, which quickly gets bloated and slowed down.
As the process begins with a save routine, I can collect data about the current "active" modules and store this is any file format - json, csv, whatever - I would then like to load that config from the file in the Gruntfile - which might be continually watching ( in case it's a problem that config can only be loaded once? -- the data would need to be grabbed again fresh before each compilation ).
simple example:
*module.json
{"js":["modal.js","toast.js","tab.js","collapse.js","form.js","toggle.js","gallery.js","helper.js","scrollspy.js","scroll.js","lazy.js","javascript.js","comment.js","push.js","nprogress.js","consent.js","search.js","anspress.js","localize.js"]}
*Gruntfile.js
// ------- configuration ------- ##
module.exports = function(grunt) {
grunt.initConfig({
// load modules ##
modules: grunt.file.readJSON('module.json'),
'uglify': {
// options etc ##
files:{
'library/asset/js/module.min.js' : '<%= modules.js %>'
}
}
});
// Development Tasks ##
grunt.registerTask(
'default'
, [ 'uglify' ]
);
}
This config runs, but does not load the data from JSON correctly - Grunt says:
Destination library/asset/js/module.min.js not written because src
files were empty.
I know Grunt can read the JS, as I can do something like the following:
*terminal
$ grunt config
Running "config" task
["modal.js","toast.js","tab.js","collapse.js","form.js","toggle.js","gallery.js","helper.js","scrollspy.js","scroll.js","lazy.js","javascript.js","comment.js","push.js","nprogress.js","consent.js","search.js","anspress.js","localize.js"]
Done.
*Gruntfile.js
// load config ##
grunt.registerTask(
'config'
, function() {
modules = grunt.file.readJSON('module.json')
grunt.log.write(JSON.stringify( modules.js ) );
}
);
Any ideas of pointers? Thanks!

The answer, was pretty simple - to include full paths to each "file" in the JSON, then Grunt parsed it withuot problems.

Related

Hashicorp Packer: ways to output a variable/local string value to a file

I have some Packer templates which generate the content for configuration files which I then need to output to a configuration file. The end goal is to upload these files to the remote machine and then use the shell provisioner, but I can't seem to figure out the correct way of doing this. My current solution relies on a local shell provisioner to write the files, then I upload them to the remote, and then run the remote provisioner.
Something like,
locals {
foo = "bar"
foo_generated = templatefile("${path.root}/template-which-uses-foo.pkrtpl", foo)
}
provisioner "shell-local" {
inline = [
"cat >${path.root}/generated/foo.conf <<'STR'\n${local.foo_generated}"
]
}
provisioner "file" {
source = "${path.root}/generated/"
destination = "/tmp/"
}
provisioner "shell" {
inline = [
"/tmp/do-something-with-foo-conf.sh",
]
}
While this works, the file generation looks very awkward, and I want to simplify it and make it more robust.
I initially started with defining sourcees for configuration file (there are many of them), in addition to the "base" ec2 source. However, from the logs it looked like Packer runs provisioners for each source inside of the build block, so it didn't seem like a good idea.
Are there better options to accomplish this?

How to deploy a raw JSON file that Webpack 4 treats as a split module?

I don't think this is an uncommon problem, but it seems like the keywords turn up many false positives. I've tried searching for "webpack dynamic configuration file", "webpack runtime load JSON file", and more. I see many results for configuring Webpack dynamically, but not many for configuring a bundled app dynamically.
I want to have a configuration file that sits in my deployment as raw JSON, i.e. no Webpack runtime or module boilerplate. Just a valid JSON file.
I want to "import" that JSON configuration in my code as I would as if it were a module, i.e. like this:
import config from './config.json'
I want Webpack to omit the JSON file from the bundle, but insert any necessary code to asynchronously request and inject the config.json waiting on the server.
I want Webpack to ignore whether ./config.json exists at build time, and to just optimistically assume it will be in the right place at runtime.
I'd love if I could specify that './config.json' is a module alias, and for Webpack to copy the aliased file to the correct location (with name config.json) in the build directory.
This will give me a raw JSON file in my deployment that my site administrator can edit without running Webpack. It lets me as a developer code as if config.json is a regular module. How can I do this? I've seen suggestions to use
externals: {
'./config.json': "require('./config.prod.json')",
},
but that won't work in the browser, where require does not exist.
I've tried this configuration with no luck. The JSON is still inlined into the bundle:
resolve: {
alias: {
'./config.json': path.resolve(__dirname, 'src/config.prod.json')
}
},
optimization: {
splitChunks: {
cacheGroups: {
config: {
test: './config.json',
chunks: 'all',
name: 'config',
priority: 100
}
}
}
}
I am using Webpack 4.
In short, you can't use
import config from './config.json'
At least not if this should run in the browser.
webpack externals would make this possible for a nodejs application.
What you really want is a normal http call.
Just get the config.json file with something like fetch.
fetch('url/config.json')
You can use copy-webpack-plugin to put the config in the correct place when webpack compiles (but do you want that if there are changes directly to this file on the server)

Batch nested templates in subdirectories using gulp-compile-handlebars

I'm using gulp compileHandlebars to compile my handlebars templates and create a page using json data and that's working great... Problem is I want to nest my handlebars templates in subdirectories but when I do this the batch process cant find the templates anymore after I add: **/*.handlebars to the batch path. See below:
gulp.task('compileHandlebars', function () {
delete require.cache[require.resolve('./src/layout.json')]
var buildSettings = require('./src/layout.json');
var templateData = buildSettings,
options = {
batch : ['./src/assets/templates/**/*.handlebars']
}
gulp.src('./src/index.handlebars')
.pipe(handlebars(templateData, options))
.pipe(rename('index.html'))
.pipe(cleanhtml())
.pipe(gulp.dest('./dist'))
.pipe(livereload());
});
The docs on npm say that batch requires an array of file paths but the example shows an array with a directory path. Your example is using blob syntax which won't work. It doesn't look like that batch will recursively look into sub-directories either... so I think you will have to make an array that includes a parent directory path for each handlebars file.
Its a bummer, I know. But you could probably automate the process of retrieving the handlebar file paths using gulp-filenames and slice off the filename from each path to get an array of directories.

Gulp js running twice for the watch statement

I see the console log statement that js task run twice once I change any of the javascript files. I wonder why it run two times for each change?
var gulp = require('gulp');
var concat = require("gulp-concat");
var uglify = require("gulp-uglify");
gulp.task('default', function() {
gulp.watch("public/js/**/*.*", ["js"]);
});
gulp.task("js", function(){
var js = [
"public/js/**/*.js",
"!public/js/api/**/*.js"
];
gulp.src(js)
.pipe(concat("app.min.js"))
.pipe(uglify())
.pipe(gulp.dest("public/js"));
});
Console
[13:02:27] Starting 'js'...
[13:02:27] Finished 'js' after 1.6 ms
[13:02:27] Starting 'js'...
[13:02:27] Finished 'js' after 5.1 ms
The problem is that you are watching the same directory which is used as the destination directory in the task you run when the change is detected. Currently, your build flow looks like this:
Imagine you're modifying a file public/js/script.js.
The watch task detects the change and starts your custom js task. As the result, the public/js/app.min.js file is created.
Since the app.min.js is inside the watched directory, the watch task detects another change, hence the js task is executed once more. You actually should run into a loop, but Gulp seems to be smart enough do detect such a cycle.
The best solution for this issue is to separate source files from the output. In your task pipe, set the destination folder to something outside the source directory, for example:
.pipe(gulp.dest("dist/js"));
After that, your project should has the following structure:
public
js
script.js
dist
js
app.min.js
grunfile.js
...
Where the public directory is used to keep the source files that are watched and the dist directory holds the output of the build. If I were you, I would reconsider renaming the public directory to something more descriptive like src, but that is up to you :)

Exclude JSON files from r.js optimizer

I use a config.json file in my application to configure the application (big surprise) after deployment, pulling them in using the requirejs-text plugin. Ideally, I would like to keep this JSON file (among others) out of the optimized built file.
Here is my app hierarchy:
app/
data/
config.json
...
scripts/
main.js // require.config in here
controllers/
ctrl.js // Uses JSON files
My current build options (through gulp) for require.js are
{
baseUrl: 'app/scripts',
mainConfigFile: 'app/scripts/main.js',
name: 'main',
out: 'main.js'
}
Since these are just flat files I want to exclude and not modules, is there a way of keeping them out of the final file?
If you list it in the dependencies as 'text!config.json', you should be able to exclude it by listing it in exclude list as 'text!config.json'. I created a fake project to test it and it worked.
So:
{
baseUrl: 'app/scripts',
mainConfigFile: 'app/scripts/main.js',
name: 'main',
out: 'main.js',
exclude: ['text!config.json']
}