1 | # Babel Debug Macros And Feature Flags
|
2 |
|
3 | This provides debug macros and feature flagging.
|
4 |
|
5 | ## Setup
|
6 |
|
7 | The plugin takes 5 types options: `envFlags`, `features`, `debugTools`, `externalizeHelpers` and `svelte`. The `importSpecifier` is used as a hint to this plugin as to where macros are being imported and completely configurable by the host. Like Babel you can supply your own helpers using the `externalizeHelpers` options.
|
8 |
|
9 | ```
|
10 | {
|
11 | plugins: [
|
12 | ['babel-debug-macros', {
|
13 | // @required
|
14 | envFlags: {
|
15 | source: '@ember/env-flags',
|
16 | flags: { DEBUG: true }
|
17 | },
|
18 | // @required
|
19 | debugTools: {
|
20 | source: 'debug-tools',
|
21 | // @optional
|
22 | assertPredicateIndex: 0
|
23 | },
|
24 | // @optional
|
25 | features: {
|
26 | name: 'ember-source',
|
27 | source: '@ember/features',
|
28 | flags: { FEATURE_A: false, FEATURE_B: true, DEPRECATED_CONTROLLERS: "2.12.0" }
|
29 | },
|
30 | // @optional
|
31 | svelte: {
|
32 | 'ember-source': "2.15.0"
|
33 | },
|
34 | // @optional
|
35 | externalizeHelpers: {
|
36 | module: true,
|
37 | // global: '__my_global_ns__'
|
38 | }
|
39 | }]
|
40 | ]
|
41 | }
|
42 | ```
|
43 |
|
44 | Flags and features are inlined into the consuming module so that something like UglifyJS will DCE them when they are unreachable.
|
45 |
|
46 | ## Simple environment and fetaure flags
|
47 |
|
48 | ```javascript
|
49 | import { DEBUG } from '@ember/env-flags';
|
50 | import { FEATURE_A, FEATURE_B } from '@ember/features';
|
51 |
|
52 | if (DEBUG) {
|
53 | console.log('Hello from debug');
|
54 | }
|
55 |
|
56 | let woot;
|
57 | if (FEATURE_A) {
|
58 | woot = () => 'woot';
|
59 | } else if (FEATURE_B) {
|
60 | woot = () => 'toow';
|
61 | }
|
62 |
|
63 | woot();
|
64 | ```
|
65 |
|
66 | Transforms to:
|
67 |
|
68 | ```javascript
|
69 | if (true) {
|
70 | console.log('Hello from debug');
|
71 | }
|
72 |
|
73 | let woot;
|
74 | if (false) {
|
75 | woot = () => 'woot';
|
76 | } else if (true) {
|
77 | woot = () => 'toow';
|
78 | }
|
79 |
|
80 | woot();
|
81 | ```
|
82 |
|
83 | ## `warn` macro expansion
|
84 |
|
85 | ```javascript
|
86 | import { warn } from 'debug-tools';
|
87 |
|
88 | warn('this is a warning');
|
89 | ```
|
90 |
|
91 | Expands into:
|
92 |
|
93 | ```javascript
|
94 | (true && console.warn('this is a warning'));
|
95 | ```
|
96 |
|
97 | ## `assert` macro expansion
|
98 |
|
99 | The `assert` macro can expand in a more intelligent way with the correct
|
100 | configuration. When `babel-plugin-debug-macros` is provided with the
|
101 | `assertPredicateIndex` the predicate is injected in front of the assertion
|
102 | in order to avoid costly assertion message generation when not needed.
|
103 |
|
104 | ```javascript
|
105 | import { assert } from 'debug-tools';
|
106 |
|
107 | assert((() => {
|
108 | return 1 === 1;
|
109 | })(), 'You bad!');
|
110 | ```
|
111 |
|
112 | With the `debugTools: { assertPredicateIndex: 0 }` configuration the following expansion is done:
|
113 |
|
114 | ```js
|
115 | (true && !((() => { return 1 === 1;})()) && console.assert(false, 'this is a warning'));
|
116 | ```
|
117 |
|
118 | When `assertPredicateIndex` is not specified, the following expansion is done:
|
119 |
|
120 | ```javascript
|
121 | (true && console.assert((() => { return 1 === 1;})(), 'this is a warning'));
|
122 | ```
|
123 |
|
124 | ## `deprecate` macro expansion
|
125 |
|
126 | ```javascript
|
127 | import { deprecate } from 'debug-tools';
|
128 |
|
129 | let foo = 2;
|
130 |
|
131 | deprecate('This is deprecated.', foo % 2);
|
132 | ```
|
133 |
|
134 | Expands into:
|
135 |
|
136 | ```javascript
|
137 | let foo = 2;
|
138 |
|
139 | (true && !(foo % 2) && console.warn('This is deprecated.'));
|
140 | ```
|
141 |
|
142 | ## Externalized Helpers
|
143 |
|
144 | When you externalize helpers you must provide runtime implementations for the above macros. An expansion will still occur, however we will emit references to those runtime helpers.
|
145 |
|
146 | A global expansion looks like the following:
|
147 |
|
148 | ```javascript
|
149 | import { warn } from 'debug-tools';
|
150 |
|
151 | warn('this is a warning');
|
152 | ```
|
153 |
|
154 | Expands into:
|
155 |
|
156 | ```javascript
|
157 | (true && Ember.warn('this is a warning'));
|
158 | ```
|
159 |
|
160 | While externalizing the helpers to a module looks like the following:
|
161 |
|
162 | ```javascript
|
163 | import { warn } from 'debug-tools';
|
164 |
|
165 | warn('this is a warning');
|
166 | ```
|
167 |
|
168 | Expands into:
|
169 |
|
170 | ```javascript
|
171 | (true && warn('this is a warning'));
|
172 | ```
|
173 |
|
174 | # Svelte
|
175 |
|
176 | Svelte allows for consumers to opt into stripping deprecated code from your dependecies. By adding a package name and minimum version that contains no deprecations, that code will be compiled away.
|
177 |
|
178 | For example, consider you are on `ember-source@2.10.0` and you have no deprecations. All deprecated code in `ember-source` that is `<=2.10.0` will be removed.
|
179 |
|
180 | ```
|
181 | ...
|
182 | svelte: {
|
183 | "ember-source": "2.10.0"
|
184 | }
|
185 | ...
|
186 | ```
|
187 |
|
188 | Now if you bump to `ember-source@2.11.0` you may encounter new deprecations. The workflow would then be to clear out all deprecations and then bump the version in the `svelte` options.
|
189 |
|
190 | ```
|
191 | svelte: {
|
192 | "ember-source": "2.11.0"
|
193 | }
|
194 | ```
|
195 |
|
196 | # Hygenic
|
197 |
|
198 | As you may notice that we inject `DEBUG` into the code when we expand the macro. We guarantee that the binding is unique when injected and follow the local binding name if it is imported directly.
|