Skip to content

Commit 1c03c60

Browse files
authored
Upgrade from webpack v4 to v5 (#2267)
Upgrade webpack and related build dependencies from v4 to v5. Also upgrade the NodeJS and npm versions used by the Main UI build as well as babel. The changes follow the recommendations of the webpack migration guide at https://webpack.js.org/migrate/5/ or are required changes for updated webpack plugins. New default values causing problems have been overwritten, e.g. devServer.compress: false because compression broke the SSE event streams. The ModuleConcatenationPlugin is not created manually in production mode anymore, as this setting broke the production build, and it is not neccassary to create that, as this plugin is automatically enabled in production mode. See https://webpack.js.org/plugins/module-concatenation-plugin/. --------- Also-by: Florian Hotze <[email protected]> Signed-off-by: Miguel Álvarez <[email protected]>
1 parent 424e646 commit 1c03c60

39 files changed

+11323
-12231
lines changed

.github/workflows/mainui.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ jobs:
2323
- uses: actions/checkout@v3
2424
- uses: actions/setup-node@v3
2525
with:
26-
node-version: '12.x'
26+
node-version: '18.x'
2727

2828
- name: Cache node modules
2929
id: cache
@@ -52,7 +52,7 @@ jobs:
5252
- uses: actions/checkout@v3
5353
- uses: actions/setup-node@v3
5454
with:
55-
node-version: '12.x'
55+
node-version: '18.x'
5656

5757
- name: Cache node modules
5858
id: cache

README.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,12 @@ You find the following repository structure:
5656

5757
In most cases, you **don't** need a Java development environment for UI development.
5858

59-
Instead, make sure you have NodeJS 16.14 (HABot: 12.16) or later and npm 8.6 (HABot: 6.14) or later installed.
59+
Instead, you need NodeJS and npm installed, you'll learn about the required versions later.
6060

61-
62-
Then identify in the `bundles` directories where the frontend code is - for instance, for the main UI it is `bundles/org.openhab.ui/web/`.
63-
Then follow the instructions in the specific add-on's `CONTRIBUTING.md` file to get started. In the main UI's case, it is located in [bundles/org.openhab.ui/CONTRIBUTING.md](https://github.com/openhab/openhab-webui/blob/master/bundles/org.openhab.ui/CONTRIBUTING.md). In many cases it will involve executing some `npm` commands to install dependencies and start a development server.
61+
Then identify in the `bundles` directories where the frontend code is - for instance, for the Main UI it is `bundles/org.openhab.ui/web/`.
62+
Then follow the instructions in the specific add-on's `CONTRIBUTING.md` file to get started, e.g. install the correct versions of NodeJS and npm.
63+
For Main UI, it is located in [bundles/org.openhab.ui/CONTRIBUTING.md](https://github.com/openhab/openhab-webui/blob/master/bundles/org.openhab.ui/CONTRIBUTING.md).
64+
In many cases it will involve executing some `npm` commands to install dependencies and start a development server.
6465

6566
However, if you want to compile the final `.jar` add-ons, we have assembled some step-by-step guides for different IDEs on our developer documentation website:
6667

bundles/org.openhab.ui.basic/CONTRIBUTING.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
## Contributing
22

3-
Javascript linting, compressing and LESS compilation is handled through Gulp. Therefore, please run `gulp` instead of changing compressed CSS/JS manually. Default Gulp task will also check the code using ESLint.
3+
You need NodeJS 18.17.0 or later and npm 9.8.1 or later installed.
4+
5+
Javascript linting, compressing and LESS compilation is handled through Gulp.
6+
Therefore, please run `gulp` instead of changing compressed CSS/JS manually.
7+
Default Gulp task will also check the code using ESLint.
48

59
Installing build dependencies:
610

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Contributing to HABot
2+
3+
You need NodeJS 12.16 or later and npm 6.14 or later installed.

bundles/org.openhab.ui.habpanel/CONTRIBUTING.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@ redirect you, if necessary.
1414

1515
## Build Environment
1616

17-
It is assumed you have ```npm```, ```bower``` and ```gulp``` available; if not,
18-
check their respective docs.
17+
You need NodeJS 16.14 or later and npm 8.6 or later installed.
18+
19+
It is assumed you have `npm`, `bower` and `gulp` available;
20+
if not, check their respective docs.
1921

2022
To build the Javascript part of HABPanel, navigate to the ```web/``` subfolder, then:
2123
1. Run ```npm install```

bundles/org.openhab.ui/CONTRIBUTING.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ The repository for web user interfaces, including this project, is located at <h
88

99
This project is built using [Vue.js](https://vuejs.org/), [webpack](https://webpack.js.org/) and [Framework7](https://framework7.io).
1010

11-
You need Node 16.14.0 or later and npm 8.6.0. Change to the `web` directory, gather the necessary dependencies with `npm install` then the scripts below will be available.
11+
You need Node 18.18.0 or later and npm 9.8.1 or later installed.
12+
13+
Change to the `web` directory, gather the necessary dependencies with `npm install` then the scripts below will be available.
1214

1315
## NPM Scripts
1416

bundles/org.openhab.ui/pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@
3737
<artifactId>frontend-maven-plugin</artifactId>
3838

3939
<configuration>
40-
<nodeVersion>v16.14.2</nodeVersion>
41-
<npmVersion>8.6.0</npmVersion>
40+
<nodeVersion>v18.18.0</nodeVersion>
41+
<npmVersion>9.8.1</npmVersion>
4242
<workingDirectory>web</workingDirectory>
4343
</configuration>
4444

bundles/org.openhab.ui/web/babel.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ module.exports = {
2424
test: {
2525
plugins: [
2626
'@babel/plugin-transform-modules-commonjs',
27-
'babel-plugin-dynamic-import-node-babel-7'
27+
'babel-plugin-dynamic-import-node'
2828
],
2929
presets: [
3030
[

bundles/org.openhab.ui/web/build/webpack.config.js

Lines changed: 84 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
const webpack = require('webpack')
22
const CopyWebpackPlugin = require('copy-webpack-plugin')
33
const HtmlWebpackPlugin = require('html-webpack-plugin')
4-
const VueLoaderPlugin = require('vue-loader/lib/plugin')
4+
const { VueLoaderPlugin } = require('vue-loader')
55
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
6-
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
6+
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
77
const TerserPlugin = require('terser-webpack-plugin')
88
const WorkboxPlugin = require('workbox-webpack-plugin')
99
const WebpackAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
@@ -12,7 +12,7 @@ const CompressionPlugin = require('compression-webpack-plugin')
1212

1313
const path = require('path')
1414

15-
function resolvePath (dir) {
15+
function resolvePath(dir) {
1616
return path.join(__dirname, '..', dir)
1717
}
1818

@@ -23,36 +23,42 @@ const isCordova = target === 'cordova'
2323

2424
const apiBaseUrl = process.env.OH_APIBASE || 'http://localhost:8080'
2525

26+
/**
27+
* @type {import('webpack').Configuration}
28+
*/
2629
module.exports = {
2730
mode: env,
2831
entry: [
2932
'./src/js/app.js'
3033
],
3134
output: {
3235
path: resolvePath(isCordova ? 'cordova/www' : 'www'),
33-
filename: 'js/app.[hash].js',
36+
filename: 'js/app.[contenthash].js',
3437
publicPath: '/',
35-
hotUpdateChunkFilename: 'hot/hot-update.js',
36-
hotUpdateMainFilename: 'hot/hot-update.json'
38+
hotUpdateChunkFilename: 'hot/[id].[fullhash].hot-update.js',
39+
hotUpdateMainFilename: 'hot/[runtime].hot-update.json'
3740
},
3841
resolve: {
42+
fallback: {
43+
"crypto": require.resolve("crypto-browserify"),
44+
"stream": require.resolve("stream-browserify"),
45+
"path": require.resolve("path-browserify"),
46+
},
3947
extensions: ['.mjs', '.js', '.vue', '.json'],
4048
alias: {
4149
vue$: 'vue/dist/vue.esm.js',
4250
'@': resolvePath('src')
4351
}
4452
},
45-
devtool: env === 'production' ? (buildSourceMaps) ? 'source-map' : 'none' : 'eval-source-map',
53+
devtool: env === 'production' ? (buildSourceMaps ? 'source-map' : false) : 'eval-source-map',
4654
devServer: {
4755
hot: true,
48-
// open: true,
49-
// compress: true,
50-
contentBase: '/www/',
51-
disableHostCheck: true,
56+
compress: false, // disable compression as this seems to break the SSE event stream
57+
static: [
58+
path.resolve(__dirname, 'www'),
59+
],
60+
allowedHosts: "all",
5261
historyApiFallback: true,
53-
// watchOptions: {
54-
// poll: 1000,
55-
// },
5662
proxy: [{
5763
context: ['/auth', '/rest', '/chart', '/proxy', '/icon', '/static', '/changePassword', '/createApiToken', '/audio'],
5864
target: apiBaseUrl
@@ -63,9 +69,22 @@ module.exports = {
6369
maxEntrypointSize: 2500000
6470
},
6571
optimization: {
66-
minimizer: [new TerserPlugin({
67-
sourceMap: true
68-
})]
72+
moduleIds: env === 'production' ? undefined : 'named',
73+
minimizer: [
74+
new TerserPlugin({
75+
terserOptions: {
76+
sourceMap: true
77+
}
78+
}),
79+
new CssMinimizerPlugin({
80+
minimizerOptions: {
81+
processorOptions: {
82+
safe: true,
83+
map: { inline: false, annotation: env !== 'production' }
84+
},
85+
},
86+
}),
87+
]
6988
},
7089
module: {
7190
rules: [
@@ -87,11 +106,6 @@ module.exports = {
87106
resolvePath('node_modules/ssr-window')
88107
]
89108
},
90-
{
91-
test: /(blockly\/.*\.js)$/,
92-
enforce: "pre",
93-
use: (buildSourceMaps) ? ["source-map-loader"] : [],
94-
},
95109
{
96110
test: /\.vue$/,
97111
use: 'vue-loader'
@@ -153,26 +167,38 @@ module.exports = {
153167
},
154168
{
155169
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
156-
loader: 'url-loader',
157-
options: {
158-
limit: 10000,
159-
name: 'images/[name].[ext]'
170+
type: 'asset',
171+
parser: {
172+
dataUrlCondition: {
173+
maxSize: 10000
174+
}
175+
},
176+
generator: {
177+
filename: 'images/[name].[ext]'
160178
}
161179
},
162180
{
163181
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac|m4a)(\?.*)?$/,
164-
loader: 'url-loader',
165-
options: {
166-
limit: 10000,
167-
name: 'media/[name].[ext]'
182+
type: 'asset',
183+
parser: {
184+
dataUrlCondition: {
185+
maxSize: 10000
186+
}
187+
},
188+
generator: {
189+
filename: 'media/[name].[ext]'
168190
}
169191
},
170192
{
171193
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
172-
loader: 'url-loader',
173-
options: {
174-
limit: 10000,
175-
name: 'fonts/[name].[ext]'
194+
type: 'asset',
195+
parser: {
196+
dataUrlCondition: {
197+
maxSize: 10000
198+
}
199+
},
200+
generator: {
201+
filename: 'fonts/[name].[ext]'
176202
}
177203
},
178204
{
@@ -185,6 +211,9 @@ module.exports = {
185211
]
186212
},
187213
plugins: [
214+
new webpack.ProvidePlugin({
215+
process: 'process/browser.js',
216+
}),
188217
new webpack.DefinePlugin({
189218
'process.env.NODE_ENV': JSON.stringify(env),
190219
'process.env.TARGET': JSON.stringify(target)
@@ -193,18 +222,9 @@ module.exports = {
193222
...(env === 'production' ? [
194223
new ESLintPlugin({
195224
extensions: ['js', 'vue']
196-
}),
197-
new OptimizeCSSPlugin({
198-
cssProcessorOptions: {
199-
safe: true,
200-
map: { inline: false }
201-
}
202-
}),
203-
new webpack.optimize.ModuleConcatenationPlugin()
225+
})
204226
] : [
205227
// Development only plugins
206-
new webpack.HotModuleReplacementPlugin(),
207-
new webpack.NamedModulesPlugin()
208228
]),
209229
new HtmlWebpackPlugin({
210230
filename: './index.html',
@@ -220,25 +240,28 @@ module.exports = {
220240
} : false
221241
}),
222242
new MiniCssExtractPlugin({
223-
filename: 'css/app.[hash].css'
243+
filename: 'css/app.[contenthash].css'
224244
}),
225-
new CopyWebpackPlugin([
226-
{
227-
from: resolvePath('src/res'),
228-
to: resolvePath(isCordova ? 'cordova/www/res' : 'www/res')
229-
},
230-
{
231-
from: resolvePath('src/manifest.json'),
232-
to: resolvePath('www/manifest.json')
233-
},
234-
{
235-
from: resolvePath('src/robots.txt'),
236-
to: resolvePath('www/robots.txt')
237-
}
238-
]),
239-
...(!isCordova ? [
245+
new CopyWebpackPlugin({
246+
patterns: [
247+
{
248+
from: resolvePath('src/res'),
249+
to: resolvePath(isCordova ? 'cordova/www/res' : 'www/res')
250+
},
251+
{
252+
from: resolvePath('src/manifest.json'),
253+
to: resolvePath('www/manifest.json')
254+
},
255+
{
256+
from: resolvePath('src/robots.txt'),
257+
to: resolvePath('www/robots.txt')
258+
}
259+
]
260+
}),
261+
...(!isCordova && env === 'production' ? [
240262
new WorkboxPlugin.InjectManifest({
241-
swSrc: resolvePath('src/service-worker.js')
263+
swSrc: resolvePath('src/service-worker.js'),
264+
maximumFileSizeToCacheInBytes: 100000000,
242265
})
243266
] : []),
244267
...(env === 'production' ? [

0 commit comments

Comments
 (0)