diff options
Diffstat (limited to 'subprojects/language-web/webpack.config.js')
-rw-r--r-- | subprojects/language-web/webpack.config.js | 232 |
1 files changed, 232 insertions, 0 deletions
diff --git a/subprojects/language-web/webpack.config.js b/subprojects/language-web/webpack.config.js new file mode 100644 index 00000000..801a705c --- /dev/null +++ b/subprojects/language-web/webpack.config.js | |||
@@ -0,0 +1,232 @@ | |||
1 | const fs = require('fs'); | ||
2 | const path = require('path'); | ||
3 | |||
4 | const { DefinePlugin } = require('webpack'); | ||
5 | const HtmlWebpackPlugin = require('html-webpack-plugin'); | ||
6 | const HtmlWebpackInjectPreload = require('@principalstudio/html-webpack-inject-preload'); | ||
7 | const MiniCssExtractPlugin = require('mini-css-extract-plugin'); | ||
8 | const { SubresourceIntegrityPlugin } = require('webpack-subresource-integrity'); | ||
9 | |||
10 | const packageInfo = require('./package.json'); | ||
11 | |||
12 | const currentNodeEnv = process.env.NODE_ENV || 'development'; | ||
13 | const devMode = currentNodeEnv !== 'production'; | ||
14 | const outputPath = path.resolve(__dirname, 'build/webpack', currentNodeEnv); | ||
15 | |||
16 | const portNumberOrElse = (envName, fallback) => { | ||
17 | const value = process.env[envName]; | ||
18 | return value ? parseInt(value) : fallback; | ||
19 | }; | ||
20 | const listenHost = process.env['LISTEN_HOST'] || 'localhost'; | ||
21 | const listenPort = portNumberOrElse('LISTEN_PORT', 1313); | ||
22 | const apiHost = process.env['API_HOST'] || listenHost; | ||
23 | const apiPort = portNumberOrElse('API_PORT', 1312); | ||
24 | const publicHost = process.env['PUBLIC_HOST'] || listenHost; | ||
25 | const publicPort = portNumberOrElse('PUBLIC_PORT', listenPort); | ||
26 | |||
27 | const resolveSources = sources => path.resolve(__dirname, 'src', sources); | ||
28 | const mainJsSources = resolveSources('main/js'); | ||
29 | const babelLoaderFilters = { | ||
30 | include: [mainJsSources], | ||
31 | }; | ||
32 | const babelPresets = [ | ||
33 | [ | ||
34 | '@babel/preset-env', | ||
35 | { | ||
36 | targets: 'defaults', | ||
37 | }, | ||
38 | ], | ||
39 | '@babel/preset-react', | ||
40 | ]; | ||
41 | const babelPlugins = [ | ||
42 | '@babel/plugin-transform-runtime', | ||
43 | ] | ||
44 | const magicCommentsLoader = { | ||
45 | loader: 'magic-comments-loader', | ||
46 | options: { | ||
47 | webpackChunkName: true, | ||
48 | } | ||
49 | }; | ||
50 | |||
51 | module.exports = { | ||
52 | mode: devMode ? 'development' : 'production', | ||
53 | entry: './src/main/js', | ||
54 | output: { | ||
55 | path: outputPath, | ||
56 | publicPath: '/', | ||
57 | filename: devMode ? '[name].js' : '[name].[contenthash].js', | ||
58 | chunkFilename: devMode ? '[name].js' : '[name].[contenthash].js', | ||
59 | assetModuleFilename: devMode ? '[name].js' : '[name].[contenthash][ext]', | ||
60 | clean: true, | ||
61 | crossOriginLoading: 'anonymous', | ||
62 | }, | ||
63 | module: { | ||
64 | rules: [ | ||
65 | { | ||
66 | test: /\.jsx?$/i, | ||
67 | ...babelLoaderFilters, | ||
68 | use: [ | ||
69 | { | ||
70 | loader: 'babel-loader', | ||
71 | options: { | ||
72 | presets: babelPresets, | ||
73 | plugins: [ | ||
74 | [ | ||
75 | '@babel/plugin-proposal-class-properties', | ||
76 | { | ||
77 | loose: false, | ||
78 | }, | ||
79 | ...babelPlugins, | ||
80 | ], | ||
81 | ], | ||
82 | assumptions: { | ||
83 | 'setPublicClassFields': false, | ||
84 | }, | ||
85 | }, | ||
86 | }, | ||
87 | magicCommentsLoader, | ||
88 | ], | ||
89 | }, | ||
90 | { | ||
91 | test: /.tsx?$/i, | ||
92 | ...babelLoaderFilters, | ||
93 | use: [ | ||
94 | { | ||
95 | loader: 'babel-loader', | ||
96 | options: { | ||
97 | presets: [ | ||
98 | ...babelPresets, | ||
99 | [ | ||
100 | '@babel/preset-typescript', | ||
101 | { | ||
102 | isTSX: true, | ||
103 | allExtensions: true, | ||
104 | allowDeclareFields: true, | ||
105 | onlyRemoveTypeImports: true, | ||
106 | optimizeConstEnums: true, | ||
107 | }, | ||
108 | ] | ||
109 | ], | ||
110 | plugins: babelPlugins, | ||
111 | }, | ||
112 | }, | ||
113 | magicCommentsLoader, | ||
114 | ], | ||
115 | }, | ||
116 | { | ||
117 | test: /\.scss$/i, | ||
118 | use: [ | ||
119 | devMode ? 'style-loader' : MiniCssExtractPlugin.loader, | ||
120 | 'css-loader', | ||
121 | { | ||
122 | loader: 'sass-loader', | ||
123 | options: { | ||
124 | implementation: require.resolve('sass'), | ||
125 | }, | ||
126 | }, | ||
127 | ], | ||
128 | }, | ||
129 | { | ||
130 | test: /\.(gif|png|jpe?g|svg?)$/i, | ||
131 | use: [ | ||
132 | { | ||
133 | loader: 'image-webpack-loader', | ||
134 | options: { | ||
135 | disable: true, | ||
136 | } | ||
137 | }, | ||
138 | ], | ||
139 | type: 'asset', | ||
140 | }, | ||
141 | { | ||
142 | test: /\.woff2?$/i, | ||
143 | type: 'asset/resource', | ||
144 | }, | ||
145 | ], | ||
146 | }, | ||
147 | resolve: { | ||
148 | modules: [ | ||
149 | 'node_modules', | ||
150 | mainJsSources, | ||
151 | ], | ||
152 | extensions: ['.js', '.jsx', '.ts', '.tsx'], | ||
153 | }, | ||
154 | devtool: devMode ? 'inline-source-map' : 'source-map', | ||
155 | optimization: { | ||
156 | providedExports: !devMode, | ||
157 | sideEffects: devMode ? 'flag' : true, | ||
158 | splitChunks: { | ||
159 | chunks: 'all', | ||
160 | cacheGroups: { | ||
161 | defaultVendors: { | ||
162 | test: /[\\/]node_modules[\\/]/, | ||
163 | priority: -10, | ||
164 | reuseExistingChunk: true, | ||
165 | filename: devMode ? 'vendor.[id].js' : 'vendor.[contenthash].js', | ||
166 | }, | ||
167 | default: { | ||
168 | minChunks: 2, | ||
169 | priority: -20, | ||
170 | reuseExistingChunk: true, | ||
171 | }, | ||
172 | }, | ||
173 | }, | ||
174 | }, | ||
175 | devServer: { | ||
176 | client: { | ||
177 | logging: 'info', | ||
178 | overlay: true, | ||
179 | progress: true, | ||
180 | webSocketURL: { | ||
181 | hostname: publicHost, | ||
182 | port: publicPort, | ||
183 | protocol: publicPort === 443 ? 'wss' : 'ws', | ||
184 | }, | ||
185 | }, | ||
186 | compress: true, | ||
187 | host: listenHost, | ||
188 | port: listenPort, | ||
189 | proxy: { | ||
190 | '/xtext-service': { | ||
191 | target: `${apiPort === 443 ? 'https' : 'http'}://${apiHost}:${apiPort}`, | ||
192 | ws: true, | ||
193 | }, | ||
194 | }, | ||
195 | }, | ||
196 | plugins: [ | ||
197 | new DefinePlugin({ | ||
198 | 'DEBUG': JSON.stringify(devMode), | ||
199 | 'PACKAGE_NAME': JSON.stringify(packageInfo.name), | ||
200 | 'PACKAGE_VERSION': JSON.stringify(packageInfo.version), | ||
201 | }), | ||
202 | new MiniCssExtractPlugin({ | ||
203 | filename: '[name].[contenthash].css', | ||
204 | chunkFilename: '[name].[contenthash].css', | ||
205 | }), | ||
206 | new SubresourceIntegrityPlugin(), | ||
207 | new HtmlWebpackPlugin({ | ||
208 | template: 'src/main/html/index.html', | ||
209 | minify: devMode ? false : { | ||
210 | collapseWhitespace: true, | ||
211 | removeComments: true, | ||
212 | removeOptionalTags: true, | ||
213 | removeRedundantAttributes: true, | ||
214 | removeScriptTypeAttributes: true, | ||
215 | removeStyleLinkTypeAttributes: true, | ||
216 | useShortDoctype: true, | ||
217 | }, | ||
218 | }), | ||
219 | new HtmlWebpackInjectPreload({ | ||
220 | files: [ | ||
221 | { | ||
222 | match: /(roboto-latin-(400|500)-normal|jetbrains-mono-latin-variable).*\.woff2/, | ||
223 | attributes: { | ||
224 | as: 'font', | ||
225 | type: 'font/woff2', | ||
226 | crossorigin: 'anonymous', | ||
227 | }, | ||
228 | }, | ||
229 | ], | ||
230 | }), | ||
231 | ], | ||
232 | }; | ||