UNPKG

18.5 kBMarkdownView Raw
1<!-- Title -->
2<h1 align="center">
3👋 Welcome to <br/><code>@expo/webpack-config</code>
4</h1>
5
6<!-- Header -->
7
8<p align="center">
9 <b>Webpack config that's optimized for running universal React and react-native-web projects</b>
10 <br/>
11 <br/>
12 <a aria-label="Circle CI" href="https://circleci.com/gh/expo/expo-cli/tree/master">
13 <img alt="Circle CI" src="https://flat.badgen.net/circleci/github/expo/expo-cli?label=Circle%20CI&labelColor=555555&icon=circleci">
14 </a>
15</p>
16
17---
18
19## [Documentation][docs]
20
21To learn more about how to use this Webpack config, check out the docs here: [Customizing the Webpack config][docs]
22
23### Contributing to the docs
24
25- [Documentation for the master branch][docs-latest]
26- [Documentation for the latest stable release][docs]
27
28## API
29
30Running `expo customize:web` will generate this default config in your project.
31
32```js
33const createExpoWebpackConfigAsync = require('@expo/webpack-config');
34
35module.exports = async function(env, argv) {
36 const config = await createExpoWebpackConfigAsync(env, argv);
37 // Customize the config before returning it.
38 return config;
39};
40```
41
42## Types
43
44### `Environment`
45
46The main options used to configure how `@expo/webpack-config` works.
47
48| name | type | default | description |
49| ------------- | --------------------------------------- | ----------- | --------------------------------------------------- |
50| `projectRoot` | `string` | required | Root of the Expo project. |
51| `https` | `boolean` | `false` | Should the dev server use https protocol. |
52| `mode` | `Mode` | required | The Webpack mode to bundle the project in. |
53| `platform` | [`ExpoPlatform`](#ExpoPlatform) | required | The target platform to bundle for. |
54| `pwa` | `boolean` | `true` | Generate the PWA image assets in production mode. |
55| `babel` | [`ExpoBabelOptions`](#ExpoBabelOptions) | `undefined` | Control how the default Babel loader is configured. |
56
57### `Environment` internal
58
59| name | type | default | description |
60| ----------- | ------------ | ----------- | ------------------------------------------------------------------ |
61| `config` | `ExpoConfig` | `undefined` | The Expo project config, this should be read using `@expo/config`. |
62| `locations` | `FilePaths` | `undefined` | Paths used to locate where things are. |
63
64### `ExpoPlatform`
65
66| type | description |
67| ---------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
68| `'ios' | 'android' | 'web' | 'electron'` | The target platform to bundle for. Native platforms are experimental and require a special native runtime. |
69
70### `ExpoBabelOptions`
71
72Control how the default Babel loader is configured.
73
74| name | type | default | description |
75| -------------------------------------- | ---------- | ----------- | ------------------------------------------------------------------------- |
76| `dangerouslyAddModulePathsToTranspile` | `string[]` | `undefined` | Add the names of node_modules that should be included transpilation step. |
77
78## Guides
79
80### PWAs
81
82- See the docs for [`expo-pwa`](../pwa) to learn more about creating the assets manually.
83- Disable automatic PWA generation with `expo build:web --no-pwa`.
84- `expo build:web` will automatically skip any PWA asset that's already linked in the project's local `web/index.html`.
85- Having sharp CLI installed globally will speed up asset generation, if it's not installed, Jimp will be used instead.
86
87#### Chrome PWAs
88
89##### Manifest.json
90
91The `manifest.json` will be created using the values in the project's `app.config.js`:
92
93Generating the `manifest.json` will be skipped if the following exists in the project's `web/index.html`:
94
95<details><summary>Show HTML</summary>
96
97```html
98<link rel="manifest" href="..." />
99```
100
101</details>
102
103If the `icons` array is defined in your `manifest.json`, then Chrome PWA icon generation will be skipped.
104
105##### Chrome PWA Icons
106
107Icons will be generated using the file defined in your `app.config.js` under `android.icon` and it'll fallback to `icon`.
108
109<details><summary>Show manifest.json</summary>
110
111```json
112{
113 "icons": [
114 {
115 "src": "...",
116 "sizes": "144x144",
117 "type": "image/png"
118 },
119 {
120 "src": "...",
121 "sizes": "192x192",
122 "type": "image/png"
123 },
124 {
125 "src": "...",
126 "sizes": "512x512",
127 "type": "image/png"
128 }
129 ]
130}
131```
132
133</details>
134
135#### Favicons
136
137Favicons will be generated using the file defined in your `app.config.js` under `web.favicon` and it'll fallback to `icon`.
138
139Asset generation for Favicons will be individually skipped if any of the following fields exist in your `web/index.html`:
140
141<details><summary>Show HTML</summary>
142
143```html
144<link rel="icon" type="image/png" sizes="16x16" href="..." />
145<link rel="icon" type="image/png" sizes="32x32" href="..." />
146<link rel="shortcut icon" href="..." />
147```
148
149</details>
150
151#### Safari PWAs
152
153Icons will be generated using the file defined in your `app.config.js` under `ios.icon` and it'll fallback to `icon`. The splash screens look at `ios.splash` and fallback to `splash`.
154
155Asset generation for Safari PWA icons/splash screens will be individually skipped if any of the following fields exist in your `web/index.html`:
156
157##### Icons
158
159<details><summary>Show HTML</summary>
160
161```html
162<link rel="apple-touch-icon" sizes="180x180" href="..." />
163```
164
165</details>
166
167##### Splash Screens
168
169<details><summary>Show HTML</summary>
170
171```html
172<link
173 rel="apple-touch-startup-image"
174 media="screen and (device-width: 320px) and (device-height: 568px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)"
175 href="..."
176/>
177<link
178 rel="apple-touch-startup-image"
179 media="screen and (device-width: 320px) and (device-height: 568px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)"
180 href="..."
181/>
182<link
183 rel="apple-touch-startup-image"
184 media="screen and (device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)"
185 href="..."
186/>
187<link
188 rel="apple-touch-startup-image"
189 media="screen and (device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)"
190 href="..."
191/>
192<link
193 rel="apple-touch-startup-image"
194 media="screen and (device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)"
195 href="..."
196/>
197<link
198 rel="apple-touch-startup-image"
199 media="screen and (device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)"
200 href="..."
201/>
202<link
203 rel="apple-touch-startup-image"
204 media="screen and (device-width: 375px) and (device-height: 812px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)"
205 href="..."
206/>
207<link
208 rel="apple-touch-startup-image"
209 media="screen and (device-width: 375px) and (device-height: 812px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)"
210 href="..."
211/>
212<link
213 rel="apple-touch-startup-image"
214 media="screen and (device-width: 414px) and (device-height: 736px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)"
215 href="..."
216/>
217<link
218 rel="apple-touch-startup-image"
219 media="screen and (device-width: 414px) and (device-height: 736px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)"
220 href="..."
221/>
222<link
223 rel="apple-touch-startup-image"
224 media="screen and (device-width: 375px) and (device-height: 667px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)"
225 href="..."
226/>
227<link
228 rel="apple-touch-startup-image"
229 media="screen and (device-width: 375px) and (device-height: 667px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)"
230 href="..."
231/>
232```
233
234</details>
235
236### Include modules
237
238You may find that you want to include universal modules that aren't part of the default modules. You can do this by customizing the Webpack config:
239
240```ts
241const createExpoWebpackConfigAsync = require('@expo/webpack-config');
242
243module.exports = async function(env, argv) {
244 const config = await createExpoWebpackConfigAsync(
245 {
246 ...env,
247 babel: {
248 dangerouslyAddModulePathsToTranspile: [
249 // Ensure that all packages starting with @evanbacon are transpiled.
250 '@evanbacon',
251 ],
252 },
253 },
254 argv
255 );
256 return config;
257};
258```
259
260**`withUnimodules`**
261
262If you're adding support to some other Webpack config like in Storybook or Gatsby you can use the same process to include custom modules:
263
264```ts
265const { withUnimodules } = require('@expo/webpack-config/addons');
266
267module.exports = function() {
268 const someWebpackConfig = {
269 /* Your custom Webpack config */
270 };
271
272 // Add Expo support...
273 const configWithExpo = withUnimodules(someWebpackConfig, {
274 projectRoot: __dirname,
275 babel: {
276 dangerouslyAddModulePathsToTranspile: [
277 // Ensure that all packages starting with @evanbacon are transpiled.
278 '@evanbacon',
279 ],
280 },
281 });
282
283 return configWithExpo;
284};
285```
286
287This method should be used instead of using the `expo.web.build.babel.include` field of the `app.json`.
288
289### Modify the babel loader
290
291If you want to modify the babel loader further, you can retrieve it using the helper method `getExpoBabelLoader` like this:
292
293```ts
294const createExpoWebpackConfigAsync = require('@expo/webpack-config');
295const { getExpoBabelLoader } = require('@expo/webpack-config/utils');
296
297module.exports = async function(env, argv) {
298 const config = await createExpoWebpackConfigAsync(env, argv);
299 const loader = getExpoBabelLoader(config);
300 if (loader) {
301 // Modify the loader...
302 }
303 return config;
304};
305```
306
307### Service workers
308
309Service workers are great for emulating native functionality, but they can also lead to a lot of confusion so they are opt-in only (starting in Expo SDK 42 and greater) in this Webpack config. To enable the default workbox plugin pass the options `{ offline: true }` to the creator method.
310
311#### How Expo service workers ... work
312
313By default Expo web has a two part service worker. The first part `web/expo-service-worker.js` setups up optional features of the Expo SDK like Notifications. The second part `web/service-worker.js` is generated by [Workbox][workbox] and manages the offline support.
314
315The entry point for the service workers is a file called: [`register-service-worker.js`](./web-default/register-service-worker.js). This file gets copied to your static folder and registered in Webpack's `entry` property (which is why you don't see it referenced in `index.html`).
316
317#### Extending the service worker
318
319If you'd like to add extra functionality, you can simply:
320
321- Eject the Webpack config: `expo customize:web`
322 - Select `web/expo-service-worker.js`
323- Modify the `web/expo-service-worker.js` however you'd like!
324
325#### Fully disabling the service worker
326
327This can have some unfortunate side-effects as application libraries like expo-notifications may expect the SW to exist. Proceed with caution.
328
329- Eject the Webpack config: `expo customize:web`
330 - Select `webpack.config.js`
331- Modify the `webpack.config.js`:
332
333```js
334const createExpoWebpackConfigAsync = require('@expo/webpack-config');
335
336module.exports = async function(env, argv) {
337 // Set offline to `false`
338 const config = await createExpoWebpackConfigAsync({ ...env, offline: false }, argv);
339 return config;
340};
341```
342
343- This will do the following:
344 - Skip registering [`register-service-worker.js`](./web-default/register-service-worker.js) in the Webpack config `entry`.
345 - Skip including the [Webpack Workbox plugin][workbox] and creating the `web/service-worker.js`.
346 - Skip including the [`web/expo-service-worker.js`](./web-default/expo-service-worker.js)
347
348[workbox]: https://developers.google.com/web/tools/workbox
349
350## Environment Variables
351
352- `EXPO_WEBPACK_DEFINE_ENVIRONMENT_AS_KEYS`: Should the define plugin explicitly set environment variables like `process.env.FOO` instead of creating an object like `proces.env: { FOO }`. Defaults to `false`. Next.js uses this to prevent overwriting injected environment variables.
353- `IMAGE_INLINE_SIZE_LIMIT`: By default, images smaller than 10,000 bytes are encoded as a data URI in base64 and inlined in the CSS or JS build artifact. Set this to control the size limit in bytes. Setting it to 0 will disable the inlining of images. This is only used in production.
354- `EXPO_WEBPACK_FAST_REFRESH`: Enable experimental fast refresh in development mode.
355
356## Exports
357
358### addons
359
360For adding features to an existing Webpack config.
361
362#### `withUnimodules`
363
364```js
365import { withUnimodules } from '@expo/webpack-config/addons';
366```
367
368Wrap your existing webpack config with support for Unimodules (Expo web). ex: **Storybook** `({ config }) => withUnimodules(config)`
369
370**params**
371
372- `webpackConfig: AnyConfiguration = {}` Optional existing Webpack config to modify.
373- `env: InputEnvironment = {}` Optional [`Environment`][#environment] options for configuring what features the Webpack config supports.
374- `argv: Arguments = {}`
375
376#### `withWorkbox`
377
378Add offline support with Workbox (`workbox-webpack-plugin`).
379
380```js
381import { withWorkbox } from '@expo/webpack-config/addons';
382```
383
384#### `withOptimizations`
385
386```js
387import { withOptimizations } from '@expo/webpack-config/addons';
388```
389
390#### `withAlias`
391
392Apply aliases to a Webpack config.
393
394```js
395import { withAlias } from '@expo/webpack-config/addons';
396```
397
398#### `withDevServer`
399
400```js
401import { withDevServer } from '@expo/webpack-config/addons';
402```
403
404#### `withNodeMocks`
405
406```js
407import { withNodeMocks } from '@expo/webpack-config/addons';
408```
409
410#### `withEntry`
411
412```js
413import { withEntry } from '@expo/webpack-config/addons';
414```
415
416#### `withTypeScriptAsync`
417
418```js
419import { withTypeScriptAsync } from '@expo/webpack-config/addons';
420```
421
422### env
423
424Getting the config, paths, mode, and various other settings in your environment.
425
426#### `getConfig`
427
428```js
429import { getConfig } from '@expo/webpack-config/env';
430```
431
432#### `getMode`
433
434```js
435import { getMode } from '@expo/webpack-config/env';
436```
437
438#### `validateEnvironment`
439
440```js
441import { validateEnvironment } from '@expo/webpack-config/env';
442```
443
444#### `getAliases`
445
446```js
447import { getAliases } from '@expo/webpack-config/env';
448```
449
450#### `getPaths`
451
452```js
453import { getPaths } from '@expo/webpack-config/env';
454```
455
456#### `getPathsAsync`
457
458```js
459import { getPathsAsync } from '@expo/webpack-config/env';
460```
461
462#### `getServedPath`
463
464```js
465import { getServedPath } from '@expo/webpack-config/env';
466```
467
468#### `getPublicPaths`
469
470```js
471import { getPublicPaths } from '@expo/webpack-config/env';
472```
473
474#### `getProductionPath`
475
476```js
477import { getProductionPath } from '@expo/webpack-config/env';
478```
479
480#### `getAbsolute`
481
482```js
483import { getAbsolute } from '@expo/webpack-config/env';
484```
485
486#### `getModuleFileExtensions`
487
488```js
489import { getModuleFileExtensions } from '@expo/webpack-config/env';
490```
491
492### loaders
493
494The module rules used to load various files.
495
496#### `imageLoaderRule`
497
498```js
499import { imageLoaderRule } from '@expo/webpack-config/loaders';
500```
501
502This is needed for webpack to import static images in JavaScript files.
503"url" loader works like "file" loader except that it embeds assets smaller than specified limit in bytes as data URLs to avoid requests.
504A missing `test` is equivalent to a match.
505
506#### `fallbackLoaderRule`
507
508```js
509import { fallbackLoaderRule } from '@expo/webpack-config/loaders';
510```
511
512"file" loader makes sure those assets get served by WebpackDevServer.
513When you `import` an asset, you get its (virtual) filename.
514In production, they would get copied to the `build` folder.
515This loader doesn't use a "test" so it will catch all modules
516that fall through the other loaders.
517
518#### `styleLoaderRule`
519
520```js
521import { styleLoaderRule } from '@expo/webpack-config/loaders';
522```
523
524Default CSS loader.
525
526### plugins
527
528```js
529import /* */ '@expo/webpack-config/plugins';
530```
531
532Custom versions of Webpack Plugins that are optimized for use with native React runtimes.
533
534#### `ExpoDefinePlugin`
535
536```js
537import { ExpoDefinePlugin } from '@expo/webpack-config/plugins';
538```
539
540Required for `expo-constants` https://docs.expo.io/versions/latest/sdk/constants/.
541This surfaces the `app.json` (config) as an environment variable which is then parsed by `expo-constants`.
542
543#### `ExpoHtmlWebpackPlugin`
544
545```js
546import { ExpoHtmlWebpackPlugin } from '@expo/webpack-config/plugins';
547```
548
549Generates an `index.html` file with the <script> injected.
550
551#### `ExpoInterpolateHtmlPlugin`
552
553```js
554import { ExpoInterpolateHtmlPlugin } from '@expo/webpack-config/plugins';
555```
556
557Add variables to the `index.html`.
558
559### utils
560
561Tools for resolving fields, or searching and indexing loaders and plugins.
562
563#### `resolveEntryAsync`
564
565```js
566import { resolveEntryAsync } from '@expo/webpack-config/utils';
567```
568
569## What it does not do
570
571- **Gzip compression:** This was supported in beta but later removed in favor of hosting providers like [Now](http://now.sh/) and [Netlify](https://www.netlify.com/) automatically compressing files in the server.
572
573## License
574
575The Expo source code is made available under the [MIT license](LICENSE). Some of the dependencies are licensed differently, with the BSD license, for example.
576
577<!-- Footer -->
578
579---
580
581<p>
582 <a aria-label="sponsored by expo" href="http://expo.io">
583 <img src="https://img.shields.io/badge/Sponsored_by-Expo-4630EB.svg?style=for-the-badge&logo=EXPO&labelColor=000&logoColor=fff" target="_blank" />
584 </a>
585 <a aria-label="expo webpack-config is free to use" href="/LICENSE" target="_blank">
586 <img align="right" alt="License: MIT" src="https://img.shields.io/badge/License-MIT-success.svg?style=for-the-badge&color=33CC12" target="_blank" />
587 </a>
588</p>
589
590[docs]: https://docs.expo.io/guides/customizing-webpack/
591[docs-latest]: https://github.com/expo/expo/blob/master/docs/pages/versions/unversioned/guides/customizing-webpack.md