Update all non-major dependencies
[ProtonMail-WebClient.git] / applications / account / webpack.config.ts
blobce237ca4e6f65353c3eb465c2f61044d177d65a3
1 import HtmlWebpackPlugin from 'html-webpack-plugin';
2 // eslint-disable-next-line lodash/import-scope
3 import template from 'lodash.template';
4 import path from 'path';
5 import type webpack from 'webpack';
6 import 'webpack-dev-server';
8 import getConfig from '@proton/pack/webpack.config';
9 import CopyIndexHtmlWebpackPlugin from '@proton/pack/webpack/copy-index-html-webpack-plugin';
10 import { addDevEntry, getIndexChunks, getSupportedEntry } from '@proton/pack/webpack/entries';
12 import type { HrefLang } from './pages/interface';
13 import { getPages } from './pages/pages';
14 import type { Parameters } from './src/pages/interface';
16 const getTemplateParameters = (
17     originalTemplateParameters: any,
18     hreflangs: HrefLang[],
19     shortLocalizedPathname: string,
20     parameters: Parameters & { pathname: string }
21 ) => {
22     let url = originalTemplateParameters.url;
23     const origin = url.replace(/\/$/, '');
24     if (parameters.pathname) {
25         url = `${origin}${parameters.pathname}`;
26     }
27     return {
28         ...originalTemplateParameters,
29         ...parameters,
30         url,
31         hreflangs: hreflangs.map(({ hreflang, pathname }) => {
32             return {
33                 hreflang,
34                 href: `${origin}${pathname}${parameters.pathname.replace(shortLocalizedPathname, '')}`,
35             };
36         }),
37     };
40 const result = async (env: any): Promise<webpack.Configuration> => {
41     const pagePromise = getPages();
43     const config = getConfig(env);
45     const plugins = config.plugins || [];
46     config.plugins = plugins;
48     const htmlPlugin = plugins.find((plugin): plugin is HtmlWebpackPlugin => {
49         return plugin instanceof HtmlWebpackPlugin;
50     });
51     if (!htmlPlugin) {
52         throw new Error('Missing html plugin');
53     }
54     const htmlIndex = plugins.indexOf(htmlPlugin);
55     const originalTemplateParameters = htmlPlugin.userOptions.templateParameters as { [key: string]: any };
57     const { pre, unsupported } = config.entry as any;
59     if (env.appMode === 'standalone') {
60         config.entry = {
61             pre,
62             ['private-index']: [path.resolve('./src/app/private.tsx'), getSupportedEntry()],
63             unsupported,
64         };
66         plugins.splice(
67             htmlIndex,
68             1,
69             new HtmlWebpackPlugin({
70                 filename: 'index.html',
71                 template: path.resolve('./src/private.ejs'),
72                 templateParameters: originalTemplateParameters,
73                 scriptLoading: 'defer' as const,
74                 chunks: getIndexChunks('private-index'),
75                 inject: 'body' as const,
76             })
77         );
79         addDevEntry(config);
81         return config;
82     }
84     config.entry = {
85         pre,
86         ['private-index']: [path.resolve('./src/app/private.tsx'), getSupportedEntry()],
87         ['public-index']: [path.resolve('./src/app/public.tsx'), getSupportedEntry()],
88         ['lite-index']: [path.resolve('./src/lite/index.tsx'), getSupportedEntry()],
89         storage: path.resolve('./src/app/storage.ts'),
90         unsupported,
91     };
93     const rewrites: any[] = [];
94     // @ts-ignore
95     config.devServer.historyApiFallback.rewrites = rewrites;
97     // Replace the old html webpack plugin with this
98     plugins.splice(
99         htmlIndex,
100         1,
101         new HtmlWebpackPlugin({
102             filename: 'private.html',
103             template: path.resolve('./src/private.ejs'),
104             templateParameters: originalTemplateParameters,
105             scriptLoading: 'defer' as const,
106             chunks: getIndexChunks('private-index'),
107             inject: 'body' as const,
108         })
109     );
110     rewrites.push({ from: /^\/u\//, to: '/private.html' });
112     plugins.splice(
113         htmlIndex,
114         0,
115         new HtmlWebpackPlugin({
116             filename: 'index.html',
117             template: path.resolve('./src/public.ejs'),
118             templateParameters: originalTemplateParameters,
119             scriptLoading: 'defer',
120             chunks: getIndexChunks('public-index'),
121             inject: 'body',
122         })
123     );
125     plugins.splice(
126         htmlIndex,
127         0,
128         new HtmlWebpackPlugin({
129             filename: 'storage.html',
130             template: path.resolve('./src/storage.ejs'),
131             templateParameters: originalTemplateParameters,
132             scriptLoading: 'defer',
133             chunks: ['storage'],
134             inject: 'body',
135         })
136     );
138     rewrites.push({ from: /^\/lite/, to: '/lite/index.html' });
139     plugins.splice(
140         htmlIndex,
141         0,
142         new HtmlWebpackPlugin({
143             filename: 'lite/index.html',
144             template: path.resolve('./src/lite.ejs'),
145             templateParameters: originalTemplateParameters,
146             scriptLoading: 'defer',
147             chunks: getIndexChunks('lite-index'),
148             inject: 'body',
149         })
150     );
152     const { pages, hreflangs } = await pagePromise;
154     pages.forEach(({ rewrite }) => {
155         rewrites.push(rewrite);
156     });
158     plugins.push(
159         new CopyIndexHtmlWebpackPlugin((source) => {
160             const compiled = template(
161                 source,
162                 // Note: We use two different template interpolations, due to <%= require('./favicon.svg' %>, which requires
163                 // a lot more effort to support properly, so we use the default loader for that and our own loader for this.
164                 {
165                     evaluate: /\{\{([\s\S]+?)\}\}/g,
166                     interpolate: /\{\{=([\s\S]+?)\}\}/g,
167                     escape: /\{\{-([\s\S]+?)\}\}/g,
168                 },
169                 undefined
170             );
172             const index = {
173                 name: 'index.html',
174                 data: compiled(
175                     getTemplateParameters(originalTemplateParameters, hreflangs, '', {
176                         title: originalTemplateParameters.appName,
177                         description: originalTemplateParameters.description,
178                         pathname: '/',
179                     })
180                 ),
181             };
183             const rest = pages.map(({ shortLocalizedPathname, filename, parameters }) => {
184                 return {
185                     name: filename,
186                     data: compiled(
187                         getTemplateParameters(originalTemplateParameters, hreflangs, shortLocalizedPathname, parameters)
188                     ),
189                 };
190             });
191             return [index, ...rest];
192         })
193     );
195     return config;
198 export default result;