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 }
22 let url = originalTemplateParameters.url;
23 const origin = url.replace(/\/$/, '');
24 if (parameters.pathname) {
25 url = `${origin}${parameters.pathname}`;
28 ...originalTemplateParameters,
31 hreflangs: hreflangs.map(({ hreflang, pathname }) => {
34 href: `${origin}${pathname}${parameters.pathname.replace(shortLocalizedPathname, '')}`,
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;
52 throw new Error('Missing html plugin');
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') {
62 ['private-index']: [path.resolve('./src/app/private.tsx'), getSupportedEntry()],
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,
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'),
93 const rewrites: any[] = [];
95 config.devServer.historyApiFallback.rewrites = rewrites;
97 // Replace the old html webpack plugin with this
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,
110 rewrites.push({ from: /^\/u\//, to: '/private.html' });
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'),
128 new HtmlWebpackPlugin({
129 filename: 'storage.html',
130 template: path.resolve('./src/storage.ejs'),
131 templateParameters: originalTemplateParameters,
132 scriptLoading: 'defer',
138 rewrites.push({ from: /^\/lite/, to: '/lite/index.html' });
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'),
152 const { pages, hreflangs } = await pagePromise;
154 pages.forEach(({ rewrite }) => {
155 rewrites.push(rewrite);
159 new CopyIndexHtmlWebpackPlugin((source) => {
160 const compiled = template(
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.
165 evaluate: /\{\{([\s\S]+?)\}\}/g,
166 interpolate: /\{\{=([\s\S]+?)\}\}/g,
167 escape: /\{\{-([\s\S]+?)\}\}/g,
175 getTemplateParameters(originalTemplateParameters, hreflangs, '', {
176 title: originalTemplateParameters.appName,
177 description: originalTemplateParameters.description,
183 const rest = pages.map(({ shortLocalizedPathname, filename, parameters }) => {
187 getTemplateParameters(originalTemplateParameters, hreflangs, shortLocalizedPathname, parameters)
191 return [index, ...rest];
198 export default result;