DEV Community

Cover image for Customizing Angular CLI 6 build  - an alternative to ng eject

Customizing Angular CLI 6 build  - an alternative to ng eject

JeB on July 27, 2018

So your Angular 6 project just went a bit beyond TODO app and you have to customize your build configuration. The question is how? Angul...
Collapse
 
chauhanvishaal profile image
chauhanvishaal

This is amazing to see the hybrid solution actually working.
Thank you very much Evgeny.

At the moment I am have two problems I am trying to resolve.
1) make use of string-replace-webpack-plugin to replace index.html content
I think I have got the configuration right however the loader rule for it just doesnt seem to execute.

I also tried a different plugin webpack-html-string-replace-plugin but it needs usage of HtmlWebpackPlugin which messes up with the ng cli default webpack configuration causing rendering issues.

2) override default builder for protractor such that it is compatible with build and serve architect/targets

Any experience customizing these ?

Loader for string-replace-webpack-plugin
{
//Replace baseUrl with appropriate value as per dev or production mode
test: /index.html$/,
exclude: /node_modules/,
use: [ { loader: StringReplacePlugin.replace({
replacements: [
{
pattern: /@baseUrl/,
replacement: function (match, p1, offset, string) {
// if (isProd)
// return "";
// else if (isDev)
return "/vmi/";
}
}
]
})
}]
}

Collapse
 
jeb profile image
JeB

Hi,
Thank you very much for the kind words.
Regarding 1 - have you added an instance of StringReplacePlugin to plugins array as the documentation suggests? Another possible issue is the order in which the loader is applied. Prepending your loader instead of appending it might work as well. Here is an example of issue that was fixed by simply changing the order.

Regarding 2 - there is no such a builder but it's definitely an option. Please create a feature request on github and I'll look into it.

If the proposed solution for 1 doesn't work, please open an issue on github so that we could continue the investigation.

Collapse
 
jeb profile image
JeB

Regarding 2: they use dev-server target for protractor tests, so using @angular-builders/dev-server should be enough.

Collapse
 
theoiorga profile image
Theo

Thank you for writing this article. I'm currently working on an app that has multiple elements, so I'm trying to build all the elements into a single file.

Following you steps, I get this error: An unhandled exception occurred: Could not find the implementation for builder @angular-builders/dev-server:generic

Does anyone has any idea why?

Collapse
 
jeb profile image
JeB

I believe you're trying to use it with a newer version of @angular-builders. It's been deprecated, you should be using @angular-builders/custom-webpack:dev-server instead. Refer to the documentation.

Collapse
 
giolf profile image
Giovanni Far • Edited

This solution seems not working correctly:
Did you try to customize the webpack.config file adding plugins such as 'webpack-dashboard' or 'webpackmonitor'?

I guess no! right?

---UPDATE---

I didn't read the "serve" part of your topic.
Now everything works perfectly

Collapse
 
rohith47 profile image
Rohith S R

Is was able to over-ride entry , output, and some plugins using this strategy. But unfortunately didn't find a way to override / stop the generation of vendor chunk by cli and generate it manually using webpack-dll plugin. Any way out ?

Collapse
 
jeb profile image
JeB

Actually stopping vendor chunk generation is pretty easy - just specify "vendorChunk": false in your dev-server (or build) configuration. Like this:

    "serve": {
      "builder": "@angular-builders/dev-server:generic",
      "options": {
        "browserTarget": "my-app:build",
        "vendorChunk": false
      },

As for DllPlugin, I have never used it so can't help you here.

I'm sure though if you figure that out there are folks that would be interested in that. So keep me posted!

Collapse
 
umananan profile image
umananan

Hi I am using @angular/cli": "~6.1.1", and Followed the steps you specefied, but getting error when trying to build the solution. Build statement used -

ng build --prod --aot --vendor-chunk --common-chunk --delete-output-path --build-optimizer --stats-json

chema validation failed with the following errors:
Data path ".builders['browser']" should have required property 'class'.
Error: Schema validation failed with the following errors:
Data path ".builders['browser']" should have required property 'class'.
at MergeMapSubscriber._registry.compile.pipe.operators_1.concatMap.validatorResult [as project]

Collapse
 
felipecarrillo100 profile image
felipecarrillo100

I need to modify the uglifyOptions from the UglifyJSPlugin, any idea how to do that?

Collapse
 
jeb profile image
JeB • Edited

Sure, please take a look at this comment. Although Angular CLI is not using UglifyJsPlugin directly, not since Webpack 4. I think you need the optimization option in Webpack.
Let me know how it turned out. If it still doesn’t work for you, kindly open an issue on github and let us continue the discussion there.

Collapse
 
felipecarrillo100 profile image
felipecarrillo100

Hi,

If you see the
node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/webpack-configs/common.js

You can see it requests

const UglifyJSPlugin = require('uglifyjs-webpack-plugin');

Then it is configured in the same file a bit further.

I'm using a 3rd party tool that requires setting the uglifyOptions.compress.unused to false.
Since the default is true I have some issues with this library.

My objective is to use extra-webpack.config.js

to modify and add the uglifyOptions compress "unused" to false. Could you give me some guidance on how to get there?

    compress: {
        pure_getters: buildOptions.buildOptimizer,
        // PURE comments work best with 3 passes.
        // See https://github.com/webpack/webpack/issues/2899#issuecomment-317425926.
        passes: buildOptions.buildOptimizer ? 3 : 1,
        // Workaround known uglify-es issue
        // See https://github.com/mishoo/UglifyJS2/issues/2949#issuecomment-368070307
        inline: wco.supportES2015 ? 1 : 3,

unused:false
}

Thread Thread
 
jeb profile image
JeB

In your plugins section add UglifyJSPlugin with compress.unused set to false.

If Angular CLI uses this plugin, your configuration will take preference and will override the compress.unused of the default UglifyJSPlugin.

Thread Thread
 
jeb profile image
JeB • Edited

@felipecarrillo100 , here are few insights:

  1. Since this commit they are using TerserPlugin instead of UglifyJsPlugin.
  2. In current implementation you cannot override the instance of a specific plugin inside minimizer array. Plugins merge was implemented for plugins array but not for the rest. If you'd like this functionality to be added, please open a feature request on github. PR is also welcome.
  3. If you need it now and don't have time to wait for this feature the only option you have is overriding the whole optimization entry. For this you have to:
    • Specify optimization: replace in mergeStrategies object in builder configuration
    • Define all the optimization configuration as it is defined in Angular along with your modifications inside your extra-webpack.config.js. Angular optimization definitions can be found in
node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/webpack-configs/common.js  

and in

node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/webpack-configs/browser.js.
Thread Thread
 
jeb profile image
JeB

You can do it easily now with version 7.4.1. Just export a function in your config file, it will receive the original config and expected to return a modified config. You can do whatever you like with the config that you receive.