I\'m working on ng2 application and I use @angular/cli
to build it. As output it emits several js files like .inline.js
, .vendor.js
et
1- use the ng build --prod --output-hashing=none
, which creates the files without the cash-buster ( the random hash).
2- Use cat
to bundle them in one file
"build":"ng build --prod --output-hashing=none",
"package":" cat dist/angular-project/{polyfills,runtime,main}.js > ./package.js",
"bundle":"npm run build && npm run package"
And use it like :
npm run bundle
I solved this in my project with a custom script that I run after ng build
.
The script does the following:
dist/index.html
file for all <link>
and <script>
tags.<link>
/<script>
tags into their own respective bundles.For example, this index.html file...
<html>
<head>
<link rel="stylesheet" src="/dist/styles.css">
<link rel="stylesheet" src="/dist/foo.css">
<link rel="stylesheet" src="/dist/bar.css">
</head>
<body>
<script src="/dist/main.js">
<script src="/dist/inline.js">
<script src="/dist/scripts.js">
<script src="/dist/foo.js">
<script src="/dist/bar.js">
</body>
</html>
...will turn into this:
<html>
<head>
<link rel="stylesheet" src="/dist/bundle.css">
</head>
<body>
<script src="/dist/bundle.js">
</body>
</html>
It works very well for me using Angular 8.
I have not seen any functionality in angular-cli that builds into one bundle, however, it should be fairly easy to do with a nodejs script or using one of the concat libraries available such as concat-files
https://www.npmjs.com/package/concat-files
install concat-files then: add a concat.js file in your project at the same level as dist folder
var concat = require('concat-files');
concat([
'./dist/inline.bundle.js',
'./dist/vendor.bundle.js',
'./dist/vendor.bundle.js'
], './dist/app.js', function(err) {
if (err) throw err
console.log('done');
});
in your package.json
under scripts
add a new script build
:
"scripts":{
"build": "ng build && node concat.js"
}
then run it npm run build
it will run the angular cli build first the run the concat.js script which will concatenate the resulting bundles
Angular CLI natively doesn't support this.
There are other solutions, including further processing with other tooling after Angular CLI finishes doing its thing, but this will hinder or remove the debugging capabilities Angular provides out-of-the-box.
As the ng eject
command is also being deprecated, the option to reconfigure webpack is not as attractive as it used to be. However, that is still technically a possibility.
The best solution I have found is the ngx-build-plus
plugin, which can be found at https://github.com/manfredsteyer/ngx-build-plus or added to a project via the ng add ngx-build-plus
Angular-CLI command currently. Once installed, it provides additional configuration options for building, including the --single-bundle true
flag that can be added to an ng build
or ng serve
command.
With that flag, a main.js file and a main.js.map file are created, already referenced in the HTML, and it'll just run like that properly out of the box, with full source mapping and debugging.
On Windows you can use type
instead of cat
and follow a similar approach proposed by @Milad:
1: Extend the scripts in package.json
"build-prod": "ng build --prod --output-hashing=none",
"package-es5": "cd dist/app-name && type runtime-es5.js polyfills-es5.js main-es5.js > bundle-es5.js",
"package-es2015": "cd dist/app-name && type runtime-es2015.js polyfills-es2015.js main-es2015.js > bundle-es2015.js",
"bundle": "npm run build-prod app-name && npm run package-es5 && npm run package-es2015",
2: Run the bundling process
npm run bundle
3: Replace the scripts automatically added in index.html
manually
<script src="bundle-es2015.js" type="module"></script>
<script src="bundle-es5.js" nomodule defer></script>
To overcome the manual step, I'm using the following workaround:
1: Create an empty placeholder.html
in the same folder as index.html
2: Copy the index.html
file and rename it to index.prod.html
2: Modify index.prod.html
with static stylesheet
and scripts
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>app-name</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
<link rel="stylesheet" href="styles.css"></head>
</head>
<body>
<app-root></app-root>
<script src="bundle-es2015.js" type="module"></script>
<script src="bundle-es5.js" nomodule defer></script>
</body>
</html>
4: Add index.html
to the assets array in angular.json
"app-name": {
"architect": {
"build": {
"options": {
"assets": [
"projects/app-name/src/index.html",
...
],
5: Modify the index entry in angular.json
to point to placeholder.html
and replace index.html
with index.prod.html
"app-name": {
"architect": {
"build": {
"configurations": {
"production": {
"index": "projects/app-name/src/placeholder.html",
"fileReplacements": [
{
"replace": "projects/app-name/src/index.html",
"with": "projects/app-name/src/index.prod.html"
},
...
],