Skip to content

Build to a single js file, not 4 files #3288

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
IvanGorbadei opened this issue Nov 26, 2016 · 19 comments
Closed

Build to a single js file, not 4 files #3288

IvanGorbadei opened this issue Nov 26, 2016 · 19 comments
Labels
P5 The team acknowledges the request but does not plan to address it, it remains open for discussion

Comments

@IvanGorbadei
Copy link

IvanGorbadei commented Nov 26, 2016

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?

@filipesilva
Copy link
Contributor

I understand why this is useful, and it could be done.

@filipesilva filipesilva added command: build P5 The team acknowledges the request but does not plan to address it, it remains open for discussion labels Dec 29, 2016
@sgraham785
Copy link

@akanieski
Copy link

I have a similar use case and would love to see this feature!

@filipesilva
Copy link
Contributor

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.

@awerlang
Copy link
Contributor

Proceed as follows:

  1. build with ng build --aot --prod --bo -sm --vendor-chunk=false --output-hashing=none
  2. in .angular-cli.json, remove the line "polyfills": "polyfills.ts",
  3. as for the file inline.bundle.js, well, inline it in your html

@bluwaterdogz
Copy link

bluwaterdogz commented Oct 31, 2018

Not using the angular cli in the problem solution, but my simple hack fix to getting one file with the package concat-files:

  1. Save this file as concat.js to root directory
    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); });
  2. Add this as build command in package.json:
    "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 :)

@kirillgroshkov
Copy link

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.

@bluwaterdogz
Copy link

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.

@awerlang
Copy link
Contributor

awerlang commented Nov 2, 2018

@bluwaterdogz see my post above. I use this approach and works flawlessly with source maps.

@kirillgroshkov
Copy link

@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:

  • main.js
  • styles.js
  • runtime.js

Vendor and polyfills are removed.

@awerlang
Copy link
Contributor

awerlang commented Nov 2, 2018

@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.

@kylecordes
Copy link

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.)

@debian4tw
Copy link

Proceed as follows:

  1. build with ng build --aot --prod --bo -sm --vendor-chunk=false --output-hashing=none
  2. in .angular-cli.json, remove the line "polyfills": "polyfills.ts",
  3. 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

@awerlang
Copy link
Contributor

@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+.

@cozzbie
Copy link

cozzbie commented Jan 25, 2019

Any news on if this was accomplished without the seeming hacks here and there?

@pawelkondraciuk
Copy link

pawelkondraciuk commented Feb 21, 2019

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,
  }
}

@miraage
Copy link

miraage commented May 28, 2019

@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

@romelgomez
Copy link

romelgomez commented Jun 10, 2019

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'));

@angular-automatic-lock-bot
Copy link

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.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Sep 30, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
P5 The team acknowledges the request but does not plan to address it, it remains open for discussion
Projects
None yet
Development

No branches or pull requests