-
Notifications
You must be signed in to change notification settings - Fork 26.1k
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
Provide the ability to remove code needed only in dev mode from the production bundle #51175
Comments
Hi Marko, we already have |
Yes, we're using the |
Well angular/packages/core/src/util/is_dev_mode.ts Lines 20 to 22 in d6efd71
And terser should be able to strip the code that is behind |
Terser is not able to tree-shake the code if the function, returning a statically analyzeble value, is used in more than 1 module. Terser is not analyzing the entire project's dependency graph, that's why // file-1.js
import { isDevMode } from './shared';
isDevMode() && console.log('file-1');
// file-2.js
import { isDevMode } from './shared';
isDevMode() && console.log('file-2');
// shared.js
export function isDevMode() {
return !!ngDevMode;
} // webpack.config.js
const TerserPlugin = require('terser-webpack-plugin');
module.exports = {
entry: ['./src/file-1.js', './src/file-2.js'],
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
terserOptions: {
compress: {
global_defs: {
ngDevMode: false,
},
},
},
}),
],
},
}; The output code: (() => {
'use strict';
var e = {
768: (e, r, o) => {
function t() {
return !1;
}
o.d(r, { X: () => t });
},
},
r = {};
function o(t) {
var n = r[t];
if (void 0 !== n) return n.exports;
var i = (r[t] = { exports: {} });
return e[t](i, i.exports, o), i.exports;
}
(o.d = (e, r) => {
for (var t in r)
o.o(r, t) &&
!o.o(e, t) &&
Object.defineProperty(e, t, { enumerable: !0, get: r[t] });
}),
(o.o = (e, r) => Object.prototype.hasOwnProperty.call(e, r)),
(0, o(768).X)() && console.log('file-1'),
(0, o(768).X)() && console.log('file-2');
})(); If we update the (()=>{"use strict"})(); |
So, to understand this correctly, in order to achieve what is needed, would angular need to:
to make this available to libs to be useful for tree shaking? |
angular/packages/core/src/util/ng_dev_mode.ts Lines 11 to 26 in 3a59de6
|
This feature request is now candidate for our backlog! In the next phase, the community has 60 days to upvote. If the request receives more than 20 upvotes, we'll move it to our consideration list. You can find more details about the feature request process in our documentation. |
I've been using a little trick in my case with ngrx which is to have 2 files in which I define what I want, for example the redux dev tool import. In dev mode I import it, while in the other file I don't. I then use the angular cli swapping file capability to use the dev one at serve time and the prod one (with nothing it in except an empty array) at build time. And because I feel like I'm absolutely not clear (end of day sorry 🙃) here's what I've got:
import { ModuleWithProviders } from '@angular/core';
import { StoreDevtoolsModule } from '@ngrx/store-devtools';
// this file will be replaced by the prod version at build time!
// this is to make sure that we don't include `store-devtools` in our prod bundle
// https://ngrx.io/guide/store-devtools/recipes/exclude
export const ngrxModules: ModuleWithProviders<any>[] = [StoreDevtoolsModule.instrument({ maxAge: 25 })];
import { ModuleWithProviders } from '@angular/core';
export const ngrxModules: ModuleWithProviders<any>[] = []; And in my Angular CLI config file:
Now, while there's a work around for this... I have to admit that this feature would be a really nice to have. It's quite convoluted and error prone to swap files at build time. Meanwhile, in case anyone needs a workaround to make sure you don't bundle the entire code for the redux dev tool or others, you know where to look :) |
Edit: I've deleted most of my answer due to making an incorrect assumption about optimized constants. Unfortunately it looks like terser isn't smart enough to optimize constants imported from environment.ts (related to the use of webpack require). I wouldn't ever want to use |
@simeyla The usecase for Explicit logs and errors in devMode & only critical errors in prodMode (and less verbose). |
This. Please. I have been wanting to do this for a while! Will help us library authors provide really clear and complete verbose logging but then have prod bundles be as small as possible. |
Note: |
Yes, that's stated by @markostanimirovic in his post. The request here would be to make it public so library maintainers can officially rely on it. |
Shouldn't we close this issue in favor of the one on the CLI repo ? angular/angular-cli#23738 |
@JeanMeche If so it needs a new title. The title of this question is much more suitable and easy to find. I did want to add an alternative approach (not sure whether or not this works for library authors since I've never created such a library). In I couldn't immediately find official mention of |
@JeanMeche, actually the CLI issue is rather working as expected, the missing part is having a public API similar to Worth to mention that the story around
|
@alan-agius4 @simeyla But how would So I personally don't see making changes to |
Would it be reasonable to support |
|
Which @angular/* package(s) are relevant/related to the feature request?
core
Description
Several NgRx libraries have features/checks that are only used in development mode (e.g. store runtime checks, component store lifecycle hooks check, store devtools, etc).
Proposed solution
Expose the
ngDevMode
/isNgDevMode
variable to the public API, so it can be used in Angular libraries that have dev mode-related functionalities, but also in user codebases if needed.This feature could significantly reduce the size of production bundles in many Angular codebases.
Alternatives considered
Currently, we can use
ngDevMode
to remove dev mode-related logic from the production bundle in the following way:However, this global variable is not part of the public API and it can be risky to rely on it.
The text was updated successfully, but these errors were encountered: