Pre-compile YAML to JSON with webpack - json

On my page, I want to use i18next and Vue.js to display translated text. For that, I want to use YAML files for better maintainability. Here on Stackoverflow, I found this old question, where #steve-hynding posted a way to configure webpack to pre-compile the YAML files into JSON. However, the syntax he used (with the rule array) doesn't work in my case, because we're using chainWebpack. I tried to rewrite the rule, but it doesn't do anything at all.
chainWebpack: config => {
config.module
.rule('yaml')
.test(/.\.yaml$/)
.use('file-loader')
.loader('file-loader')
.options({
name: '[path][name].json',
context: 'src'
})
.end()
.use('yaml-loader')
.loader('yaml-loader')
.end();
}
How can I make webpack extract the *.yaml files from a specified folder, compile it into JSON and put it into a specified folder in the public dir?

Related

Modify existing YAML values using Gulp

I'm pretty new to YAML and I feel like I missing something or making my own life harder than it should be.
I'm using Gulp to run a bunch of tasks to minify CSS/JS and lint my code, but for the final build I need to modify a YAML file that contains some configuration values.
This is part of my YAML file:
- adx_name: RedirectUri
adx_sitesettingid: 3745e5fe-2b95-eb11-b1ac-000d3a2cd507
adx_value: https://example.com/signin
The YAML file contains a bunch of config but I just need to change the adx_value where adx_name = RedirectUri.
I don't seem to be able to find any Gulp plugins that work with YAML directly, other than those that are able to read YAML or append to YAML files. What I need to be able to do it edit the file and write new values at the correct location in the file.
You can do this pretty easily with gulp-replace.
gulp.task('yaml-replace', function () {
return gulp.src('./test.yaml')
.pipe(replace(/(?<=adx_name:\s)(RedirectUri)/g, 'myReplacement')) // positive lookbehind
.pipe(gulp.dest('./yaml'));
});
The replace function can take a string or regex and replace with a string or function.
Result:
- adx_name: myReplacement
adx_sitesettingid: 3745e5fe-2b95-eb11-b1ac-000d3a2cd507
adx_value: https://example.com/signin

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)

Is it possible to ignore files when copying directories in a yeoman generator?

I'm trying to write a yeoman generator and at one point I need to copy the files/folders of a github repo to the current working directory, eg:
this.remote('owner', 'repo', function (err, remote) {
remote.directory('.', '.');
});
However I want to ignore some of the files in this repo, is it possible to do so? I found the function responsible for this but it doesn't seem to be a clear way to do it, there's a process function that you can pass but I'm not sure if you can "cancel" a file being copied if it matches a certain pattern.
From the mem-fs-editor docs:
For a globified from, you can optionally pass in an
options.globOptions object to change its pattern matching behavior.
See the options here:
Example:
this.fs.copy("<from path>/**", "<to path>",
{
globOptions: {
ignore: [
globs to ignore...
]
}
}
);
You should rely on the this.fs object rather than the old depreciated files methods.
Helper methods on this.fs support glob patterns, so ignoring some files become trivial.
You can learn more about Yeoman file system here: http://yeoman.io/authoring/file-system.html

how base option affects gulp.src & gulp.dest

I encountered an issue trying to copy a set of files and when calling .dest('some folder') the entire folder structure was lost.
I searched and found an answer suggesting that I should provide {base:'.'} as an option on my call to gulp.src(...) to resolve this issue.
The documentation for gulp.src options only says that its options are:
Options to pass to node-glob through glob-stream.
Looking into node-glob documentation for its options base is not listed there at all.
And the glob-stream options documentation only states that
"the Default is everything before a glob starts (see glob-parent)"
So no much help here either.
So, what effect does the base option passed to gulp.src have on the viny6l files in the created stream and how does it effect the gulp.dest command ?
(You're not looking at the official gulp documentation. http://github.com/arvindr21/gulp is just some guy's fork of the gulpjs github repo. The official repo is http://github.com/gulpjs/gulp/ where the base option is indeed documented.)
To answer your question:
If you don't specify the base option yourself, then everything before the first glob in your gulp.src() paths is automatically used as the base option and ommitted when writing to the destination folder.
Say you have the following files:
some/path/example/app/js/app.js
some/path/example/vendor/js/vendor.js
some/path/example/vendor/lib/js/lib.js
And this is your Gulpfile.js:
gulp.src('some/path/**/js/*.js')
.pipe(gulp.dest('output'));
In this case everything before the ** is automatically used as your base option. So the above is essentially equivalent to this:
gulp.src('some/path/**/js/*.js', {base:'some/path/'})
.pipe(gulp.dest('output'));
What this means is that some/path/ is stripped from the path of every file that matches the pattern in gulp.src(). The resulting structure in the output folder looks like this:
output/example/app/js/app.js
output/example/vendor/js/vendor.js
output/example/vendor/lib/js/lib.js
So a certain part of the directory structure of your source files is indeed lost. How much of your directory structure you lose depends on where the first glob in your gulp.src() pattern is.
If you want to avoid this you have to explicitly specify the base option:
gulp.src('some/path/**/js/*.js', {base:'.'})
.pipe(gulp.dest('output'));
Now some/path/ will not be stripped from your file paths, resulting in the following folder structure in output:
output/some/path/example/app/js/app.js
output/some/path/example/vendor/js/vendor.js
output/some/path/example/vendor/lib/js/lib.js
EDIT: If you pass an array of patterns to gulp.src() there's no way to specify a different base option for each of the array elements. This for example won't work:
gulp.src(
['source1/examples/**/*.html',
'source2/examples/**/*.html'],
{ base: ['source1/', // Doesn't work.
'source2/']} // Needs to be a string.
).pipe(gulp.dest('dist'));
Instead you have to follow the "Using multiple sources in one task" recipe. This lets you merge two streams each of which can receive its own base option:
var merge = require('merge-stream');
gulp.task('default', function() {
merge(gulp.src('source1/examples/**/*.html', {base: 'source1/'}),
gulp.src('source2/examples/**/*.html', {base: 'source2/'}))
.pipe(gulp.dest('dist'));
});

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']
}