Merge branch 'INDA-330-pii-update' into 'main'
[ProtonMail-WebClient.git] / applications / pass / webpack.config.ts
blob17712bfa8f6dd557ae71b067480da23817999eb1
1 import path from 'path';
2 import webpack from 'webpack';
3 import { WebpackManifestPlugin } from 'webpack-manifest-plugin';
5 import getConfig from '@proton/pack/webpack.config';
6 import { NamedDeterministicChunkIdsPlugin } from '@proton/pass/utils/webpack/chunks/plugin';
8 const CRITICAL_OFFLINE_ASSETS = [
9     /** main assets */
10     'index.css',
11     'index.html',
12     'index.js',
14     /* runtime */
15     'pre.js',
16     'runtime.js',
17     'unsupported.js',
19     /* workers */
20     'core.worker.js',
21     'crypto-worker.js',
23     /* icons */
24     'sprite-icons.svg',
25     'file-icons.svg',
27     /* wasm */
28     'wasm',
29     'node_modules_pmcrypto_node_modules_openpgp_dist_lightweight_argon2id_min_mjs',
32 const result = (env: any): webpack.Configuration => {
33     const config = getConfig(env);
34     const version = env.version;
36     config.plugins?.push(
37         new webpack.DefinePlugin({
38             BUILD_TARGET: JSON.stringify('web'),
39             DESKTOP_BUILD: false,
40             ENV: JSON.stringify(process.env.NODE_ENV ?? 'development'),
41             EXTENSION_BUILD: false,
42             OFFLINE_SUPPORTED: true,
43         })
44     );
46     if (config.resolve) config.resolve.alias = { 'proton-pass-web': path.resolve(__dirname, 'src/') };
47     if (config.devServer) config.devServer.headers = { 'Service-Worker-Allowed': '/' };
49     if (config.output) {
50         const chunkFilename = config.output.chunkFilename;
51         config.output.chunkFilename = (pathData, assetInfo) => {
52             const chunkName = pathData?.chunk?.name;
53             if (chunkName && chunkName.startsWith('pass.service-worker')) return `[name].js?v=${version}`;
55             if (typeof chunkFilename === 'function') {
56                 const result = chunkFilename(pathData, assetInfo);
57                 /** `NamedDeterministicChunkIdsPlugin` will preserve `[name]` as
58                  * the named chunkId - as such replace it with the `[id]` to ensure
59                  * filenames match the deterministic chunkId */
60                 return result.replace('[name]', '[id]');
61             }
63             return chunkFilename ?? '[id].js';
64         };
66         config.output.webassemblyModuleFilename = 'assets/[hash].wasm';
67     }
69     if (config.plugins) {
70         config.plugins.push(new NamedDeterministicChunkIdsPlugin());
71         config.plugins.push(
72             new WebpackManifestPlugin({
73                 fileName: 'assets/offline.json',
74                 filter: (file) => {
75                     /** exclude sourcemaps */
76                     if (file.name.includes('.map')) return false;
77                     return CRITICAL_OFFLINE_ASSETS.some((asset) => file.name.includes(asset));
78                 },
79                 generate: (seed, files) =>
80                     files.reduce((manifest, file) => {
81                         const key = (() => {
82                             if (file.path.includes('argon2')) return 'argon2';
83                             if (file.path.includes('wasm')) return file.path.match(/[^/]+\.wasm$/)![0];
84                             return file.name;
85                         })();
87                         manifest[key] = file.path;
88                         return manifest;
89                     }, seed),
90             })
91         );
92     }
94     config.experiments = {
95         ...config.experiments,
96         asyncWebAssembly: true,
97     };
99     return config;
102 export default result;