How to serve a json file with parcel without bundling it? - json

I'm making a project with parcel and typescript. It works great, but for one library I'm using, I would need to host a bunch of .json-files at a fixed directory:
The files look as following:
index.html
index.ts
tiles/
| file.json
| file0.json
| subdirectory with *.json
In package.json, I include them as parcel *.html tiles/* (for start) and parcel build index.html tiles/*, but this results in the json files to be build into some .js file. I however need them to be served as is.
Any hints on how to tell parcel not to bundle them?

There is a npm-package doing exactly this: https://www.npmjs.com/package/parcel-plugin-static-files-copy
npm install -D parcel-plugin-static-files-copy to install (for development only)
Then, in package.json, add:
"staticFiles": {
"staticPath": [
{
"staticPath": "tiles", -- copy all files from this directory at the root from your project...
"staticOutDir": "tiles/" -- ... to this directory in dist/, so it becomes dist/tiles/<files>
}
]
}
```
Note that you have to define a `staticPath` in the list `staticPath`, this is a bit confusing at first.

You can override the transformer plugin used for JSON files in the .parcelrc file. It defaults to using #parcel/transformer-json, but you can use #parcel/transformer-raw to treat JSON files as assets.
.parcelrc
{
"extends": "#parcel/config-default",
"transformers": {
"*.json": ["#parcel/transformer-raw"]
}
}

If you're using Parcel 2, you can do something like this:
import jsonUrl from 'url:./data.json'
// Fetch the file asynchronously from the URL
fetch(jsonUrl)
.then(response => response.json())
.then(json => ...)
... etc. ...

Related

How to ng build angular with json so that after ng build, json values can be replaced manually to show different results?

If not possible any alternative to ng build?
Problem is in the build json values are embeded in main.js making impossible to alter json values later. I want to create a report in HTML with a json file format using angular which can be viewed offline. So later when i wish to change value, i only need to alter value in json file.
You want to create a config file, add the file in angular.json so that it's included in the dist folder when your app is built, then add a couple of properties to the tsconfig file so that your typescript knows how to import a json file and treat it as a module.
I wrote a detailed blog post walking you through how to do it step-by-step and how it works. You can find that here => https://dev.to/kylerjohnson26/build-your-angular-app-once-deploy-anywhere-5ggk
This will allow you to easily interact with your json config values from your code simply by importing it wherever you want to use it. Most of all, most deployment tools (like Octopus) have native support for json config files so you can easily replace values based on which environment you're deploying to. This is the simplest way to setup your config so that you can "build once and deploy anywhere".
a way is to add your json in assets in your angular-json file
"apps": [
{
"root": "src",
"outDir": "dist",
"assets": [
"assets",
"favicon.ico",
"myJson.json",
"web.config"
],
here is supposed that the file is in same folder of the main. If you put it in assets folder, you can try user the path "./assets/myJson.json",
in this way, after build, the file will be left and you can edit it.
One approach would be to store your JSON in the assets folder and then fetch it with an HTTP GET. Then when your app is deployed, you can simply swap out the JSON file for a different one.
Store the json - assets/test.json:
{
"message": "hello"
}
Get the JSON with HttpClient:
#Component({
selector: 'my-app',
templateUrl: './my-app.component.html'
})
export class MyAppComponent implements OnInit {
constructor(private http: HttpClient) {
}
ngOnInit() {
this.http.get('/assets/test.json').subscribe(resp => {
alert(resp['message']);
});
}
}
Here's a stackblitz demonstrating this.

Reading application settings from JSON file in angular application

I have implemented the application configuration to be read from JSON file from my angular application so that it is easily configurable post deploment.
We use Octopus deployment tool to deploy the angular application. As you are aware the having he enviornment.ts file gets generated as js file and it
is very difficult to manipulate the settings in Octopus by reading the JS file. Hence I have created config.JSON file that would be outputted to the dist folder and
Octopus deploy can consume the JSON file to make changes whenever needed.
Currently the application is reading values from enviornment ts file which in turn is reading the values set in the Config.JSON file.
I would like to know if my approach is correct ?
Config.JSON
{
"settings": {
"production": false,
"userIdleMinutes": "10",
"corePingIntervalSeconds": "10",
"baseUrl": "http://localhost:57973",
"loginUrl": "/Login",
"adminUrl": "/Admin"
}
}
enviornment.ts
import config from '../assets/config.json'
// The file contents for the current environment will overwrite these during build.
// The build system defaults to the dev environment which uses `environment.ts`, but if you do
// `ng build --env=prod` then `environment.prod.ts` will be used instead.
// The list of which env maps to which file can be found in `.angular-cli.json`.
export const environment = {
production: config.settings.production,
baseUrl: config.settings.baseUrl,
loginUrl:config.settings.loginUrl,
adminUrl: config.settings.adminUrl,
userIdleMinutes: config.settings.userIdleMinutes,
corePingIntervalSeconds: config.settings.corePingIntervalSeconds
};
if you are using octopus, instead of doing that, in your environment.prod.ts add some tokens and replace them on each environment by octopus
(right now I don't have access to show you how, but something like below)
environment.prod.ts
export const environment = {
production: #{production},
baseUrl: "#{baseUrl}",
//... rest of your configs
};
then add a step to replace these variables with the variables defined in environment in main.*.js file on each deployment

Babel cli preset config

Due to some certain reason I don't wish to use .babelrc file even though I'm well aware of the fact that I'm supposed to follow the rules. Anyways, for the run time I'm using the following code
require('babel-register')({
babelrc: false,
presets: [
'stage-0',
['env', {
targets: {
node: 'current'
}
}]
],
plugins: [
'transform-async-to-generator',
'syntax-async-functions'
]
});
require('../server/core');
Now I need the same config to be executed from shell. E.g.
babel config --out-dir
Thanks for your help
There is currently no way to pass plugin/preset options via CLI arguments. https://github.com/babel/babel/issues/4161 so if you don't wish to use a .babelrc then there's no easy way to get args in via the CLI command.
Given that, your next best bet would be to use something like gulp-babel to put together your own build pipeline with programmatic arguments like babel-register has.

Yii2 assets and gulp

I learn Yii2 and tried to use gulp with it in way like described here. I created gulp config with following content:
var gulp = require('gulp');
var uglify = require('gulp-uglify');
var cssMin = require('gulp-css');
var rename = require('gulp-rename');
var minimist = require('minimist');
var options = minimist(process.argv.slice(2), {string: ['src', 'dist']});
var destDir = options.dist.substring(0, options.dist.lastIndexOf("/"));
var destFile = options.dist.replace(/^.*[\\\/]/, '');
// Use `compress-js` task for JavaScript files 
gulp.task('compress-js', function () {
    return gulp.src(options.src)
        .pipe(uglify())
        .pipe(rename(destFile))
        .pipe(gulp.dest(destDir))
});
// Use `compress-css` task for CSS files
gulp.task('compress-css', function () {
    return gulp.src(options.src)
        .pipe(cssMin())
        .pipe(rename(destFile))
        .pipe(gulp.dest(destDir))
});
I use this file for my bundle:
<?php
namespace app\assets;
use yii\web\AssetBundle;
class AppAsset extends AssetBundle
{
    public $basePath = '#webroot';
    public $baseUrl = '#web';
    public $css = [
        'css/site.css',
    ];
    public $js = [
    ];
    public $jsOptions = [
        'position' => \yii\web\View::POS_HEAD
    ];
    public $depends = [
        'yii\web\YiiAsset',
        'yii\bootstrap\BootstrapAsset',
    ];
}
And, after all, I use this config for asset command
<?php
Yii::setAlias('#webroot', str_replace('\\', '/',  __DIR__) . '/web');
Yii::setAlias('#web', '/');
return [
    'jsCompressor' => 'gulp compress-js --gulpfile gulpfile.js --src {from} --dist {to}',
    'cssCompressor' => 'gulp compress-css --gulpfile gulpfile.js --src {from} --dist {to}',
    'bundles' => [
        'app\assets\AppAsset'
    ],
    'targets' => [
        'all' => [
            'class' => 'yii\web\AssetBundle',
            'basePath' => '#webroot/assets',
            'baseUrl' => '#web/assets',
            'js' => 'combined-{hash}.js',
            'css' => 'combined-{hash}.css',
            'depends' => [
            ],
        ],
    ],
    // Asset manager configuration:
    'assetManager' => [
        'basePath' => '#webroot/assets',
        'baseUrl' => '#web/assets',
        'linkAssets' => true
    ],
];
But, when I try to run php yii asset assets-config.php config/assets-prod.php combined files and configuration file config/assets-prod.php generate, but in web/assets directory exists a lot of symlinks (or direct copies if linkAssets === true) of files and folders, which is bundle dependencies themselves. They generate via publish() method of AssetManager. Why Yii don't clean these folders and files after compilation process? Or maybe I do something wrong?
Your script or css files can depend on their sources. For instance you combine css files. One file (from folder "foldername" its important) have following rule
i.sprite-icons {
url(./icons.png)
}
yii concatenate files & move them into "/assests" folder. So Yii also modifies urls. As a result you have following css rule.
i.sprite-icons {
url(./foldername/icons.png)
}
Yii run compressor only after it concatenates files. In your case - gulp.

Module.exports vs plain json for config files

I see multiple ways to create config files in Node.js. One uses module.exports in js file, one just use plain json object.
// config1.js
module.exports = {
config_1: "value 1",
config_2: "value 2"
}
// config2.json
{
"config_1": "value 1",
"config_2": "value 2"
}
Is there any advantages of using module.exports in config file? What are the differences?
javascript CommonJS Module
comments
conditionals
loops and such to populate defaults
code to change config based on NODE_ENV or similar
code to look for external files for SSL keys, API credentials, etc
easier to have fallbacks and defaults
JSON file
easy to parse and update with external tools
compatible with pretty much every programming language out there
pure data that can be loaded without being executed
easy to pretty print
JSON could start as the basis and all the code items described above about CommonJS module could live in a config.js module that reads config.json as it's starting point
So I always start with a commonjs module for the convenience, but keep any logic in there simple. If your config.js has bugs and needs tests, it's probably too complicated. KISS. If I know for a fact other things are going to want poke around in my config, I'll use a JSON file.
Thanks #jonathan-ong, looks like config.js (NOT JSON file) works as expected and I could put some comments.
module.exports = {
// Development Environment
development: {
database: {
host: '127.0.0.1',
login: 'dev',
password: 'dev'
}
},
// Production Environment
production: {
database: {
host: '127.0.0.1',
login: 'prod',
password: 'prod'
}
}
};
js files have their own perks as #Peter Lyons mentioned. But if I don't have to access external resources for API keys and etc. I would prefer JSON for config files.
Simple reason being I would not have to touch my code for just for the sake of making changes to config files. I can simply make an API to edit these json files to add,update or remove any configuration key-value pair. Even add whole new config file for a separate environment using an API.
And use config module to consume these configurations