Sorry if it not the right place for such a question, but Angular-Cli team looks like the best answerer for it.
Angular-cli builds all code into several js files: main.bundle.js, inline.bundle.js, scripts.bundle.js and styles.bundle.js.
There are many people who would love to see only one file mostly for performance reasons.
Just one .js file with everything.
1)Is it configurable/possible?
2)Was the configuration with 4 files done on purpose, will there be huge architectural complications caused by moving to a single file?
I understand why this is useful, and it could be done.
this is useful https://github.com/dfsq/compressJS.sh
I have a similar use case and would love to see this feature!
This isn't something we're looking at doing nowadays. It's good to have several files for caching purposes, since part of your app might still be cached on the client.
Proceed as follows:
ng build --aot --prod --bo -sm --vendor-chunk=false --output-hashing=none
"polyfills": "polyfills.ts",
inline.bundle.js
, well, inline it in your htmlNot using the angular cli in the problem solution, but my simple hack fix to getting one file with the package concat-files:
var concat = require('concat-files');
var compile_to = 'ADD_COMPILE_LOCATION_AND_NAME_HERE'
concat([
'./dist/main.js',
'./dist/runtime.js',
'./dist/polyfills.js'
], compile_to, function(err) {
if (err) throw err
console.log('Compiled to , ', compile_to);
});
"build": "ng build --output-hashing none && node concat"
Obviously will not run if you are not outputting any of these files or if the output directory is different than the current. The build command can be further customized, but is a good starting place. LMK if theres anything I should add and hope it helps someone :)
Well, it's easy to just concat js files in a build step. What's not easy is that we would like sourceMaps (*.map.js
) to be preserves, since they are consumed by Sentry in case error occurs and allows to pinpoint the error down to typescript line of code and position. If we concat - we lose sitemaps:(
Any solution to that?
BTW, we're using ngx-build-plus
, so we have a way to extend Webpack config.
No sir I dont, would also be interested in a solution that preserves source maps but I dont work on angular or webpack, just providing a solution for people who want 1 file output based on what we do in production.
@bluwaterdogz see my post above. I use this approach and works flawlessly with source maps.
@bluwaterdogz see my post above. I use this approach and works flawlessly with source maps.
I'm doing the same, but I still have 3 bundles:
Vendor and polyfills are removed.
@kirillgroshkov
inline.bundle.js
was renamed runtime.js
. I recommend to inline it on your page html:
<!-- node with swig.js -->
<script>{% include '../../../public/dist/js/runtime.js' ignore missing %}</script>
Regarding styles.js
, I don't have this one. Maybe because the styles
array on my angular.json file is empty.
The old "inline" made sense to be in-line, and I suspect whoever initially named it that way had this in mind. I had opened issue #2307 long ago, soon after this design appeared. However I believe the team has already considered this and decided not to put the content inline; instead it was renamed runtime.
(However, in some projects I do something similar to the above, mechanically putting this small amount of frequently changing JavaScript in the HTML file to save one round-trip per fresh page load. I find this worthwhile, between now and when HTTP2 becomes universal.)
Proceed as follows:
- build with
ng build --aot --prod --bo -sm --vendor-chunk=false --output-hashing=none
- in .angular-cli.json, remove the line
"polyfills": "polyfills.ts",
- as for the file
inline.bundle.js
, well, inline it in your html
Wouldn't this remove the polyfills file? dropping support for IE11 or order browsers
@debian4tw
Yes, it removes the polyfills file. Or better, doesn't create one.
Yet it works because then the polyfills will then be included in the main bundle, as long as you have a import './polyfills';
as the first statement in your main file.
I'm unsure why so many people dislike this solution. AFAIK it's the only published workaround that works. I've been using it for ~2 years. The downside is not being officially supported and so may stop working any time. It works with v6.2.1, I believe it will require some upkeep from what I've seen from v7+.
Any news on if this was accomplished without the seeming hacks here and there?
You could use @angular-builders/custom-webpack. Example usage:
angular.json
"architect": {
"build": {
"builder": "@angular-builders/custom-webpack:browser",
"options": {
"customWebpackConfig": {
"path": "./webpack.extra.config.js"
},
}
},
"configurations": {
"production": {
"outputHashing": "none",
"vendorChunk": false
}
}
}
webpack.extra.config.js
module.exports = {
optimization: {
runtimeChunk: false,
}
}
@filipesilva so what would you suggest to users who are forced to host their apps in environments where single file is required? E.g. users must provide a runtime token in order to load a script, but service workers are not allowed due to support of IE11
Here there are a simple Gulp Script that concatenates the principal JS files (main, polyfills, vendor, runtime), Case Angular 7. The taks name is singleJSFILE
'use strict';
const gulp = require('gulp');
const gulpif = require('gulp-if');
const imagemin = require('gulp-imagemin');
const htmlmin = require('gulp-htmlmin');
const uglify = require('gulp-uglify');
const uuidv1 = require('uuid/v1');
const csso = require('gulp-csso');
const concat = require('gulp-concat');
const del = require('del');
const replace = require('gulp-replace');
const ALL_FOR_ONE_FILE_HASH = uuidv1();
/**
* Tasks:
* - Clean
*/
gulp.task('clean', del.bind(null, ['gulp_build']));
/**
* Tasks:
* - Move PWA files
*/
gulp.task('pwa_files', function () {
return gulp.src([
'ng_build/ngsw-worker.js',
'ng_build/safety-worker.js',
'ng_build/worker-basic.min.js',
])
.pipe(gulp.dest('gulp_build'));
});
/**
* Tasks:
* - Uglify JS
* - Minify CSS and HTML
*/
gulp.task('pack', function () {
return gulp.src([
'ng_build/*',
'ng_build/**/*',
'!ng_build/ngsw-worker.js',
'!ng_build/safety-worker.js',
'!ng_build/worker-basic.min.js',
])
// Scripts
.pipe(gulpif('*.js', uglify()))
// Styles
.pipe(gulpif('*.css', csso()))
// HMTL
.pipe(gulpif('*.html', htmlmin({collapseWhitespace: true})))
// Images
.pipe(gulpif('*.png', imagemin()))
.pipe(gulpif('*.svg', imagemin()))
.pipe(gulpif('*.svg', imagemin()))
.pipe(gulpif('*.ico', imagemin()))
// .pipe(gulpif('*.jpg', imagemin()))
// DEST
.pipe(gulp.dest('gulp_build'));
});
/**
* Tasks:
* - Build an single JS FILE
*/
gulp.task('packJS', function () {
return gulp.src([
'gulp_build/main.*.js',
'gulp_build/es2015-polyfills.*.js',
'gulp_build/polyfills.*.js',
'gulp_build/runtime.*.js',
'gulp_build/vendor.*.js',
])
.pipe(concat('all.' + ALL_FOR_ONE_FILE_HASH + '.js'))
.pipe(gulp.dest('gulp_build'));
});
/**
* Tasks:
* - Update index.html with the "single JS FILE name"
*/
gulp.task('allForOneMain', function(){
return gulp.src([
'gulp_build/index.html',
])
.pipe(replace(/main.+?js/g, 'all.' + ALL_FOR_ONE_FILE_HASH + '.js'))
.pipe(replace(/es2015-polyfills.+?js/g, ''))
.pipe(replace(/polyfills.+?js/g, ''))
.pipe(replace(/vendor.+?js/g, ''))
.pipe(replace(/runtime.+?js/g, ''))
.pipe(gulp.dest('gulp_build'));
});
gulp.task('singleJSFILE', gulp.series('packJS', 'allForOneMain'));
gulp.task('default', gulp.series('clean', 'pack', 'singleJSFILE', 'pwa_files'));
This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.
Read more about our automatic conversation locking policy.
_This action has been performed automatically by a bot._
Most helpful comment
Proceed as follows:
ng build --aot --prod --bo -sm --vendor-chunk=false --output-hashing=none
"polyfills": "polyfills.ts",
inline.bundle.js
, well, inline it in your html