GUACAMOLE-773: Use Webpack rather than Webpack+Gulp.

This commit is contained in:
Michael Jumper
2021-04-06 10:42:02 -07:00
parent 1ef61687d8
commit 5f0ab7b3f3
15 changed files with 3599 additions and 2683 deletions

View File

@@ -1 +0,0 @@
org.webjars.bower:angular-module-shim:jar:0.0.4

View File

@@ -1,2 +1 @@
src/main/frontend/dist/**/*
src/main/frontend/generated/**/*

View File

@@ -1,4 +1,3 @@
*~
node_modules
dist
generated

View File

@@ -1,34 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/**
* @fileoverview External APIs referenced by the source of the Guacamole webapp
* and its dependencies.
* @externs
*/
// guacamole-common-js
const Guacamole = {};
// Web Storage API
const localStorage = {};
// matchMedia() function of Window object
const matchMedia = function matchMedia(str) {}

View File

@@ -1,105 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
const angularFilesort = require('gulp-angular-filesort');
const cleanCss = require('gulp-clean-css');
const concat = require('gulp-concat');
const del = require('del');
const gulp = require('gulp');
const ngHtml2Js = require("gulp-ng-html2js");
const sourcemaps = require('gulp-sourcemaps');
const webpack = require('webpack-stream');
// Clean build files
gulp.task('clean', (callback) => del([
'dist',
'generated'
], callback));
// Build monolithic, minified CSS source
gulp.task('build-css',
() => gulp.src([
'node_modules/@simonwep/pickr/dist/themes/monolith.min.css',
'src/app/**/*.css'
])
.pipe(sourcemaps.init())
.pipe(concat('guacamole.min.css'))
.pipe(cleanCss())
.pipe(sourcemaps.write('./'))
.pipe(gulp.dest('dist'))
);
// Pre-cache AngularJS templates
gulp.task('build-template-js',
() => gulp.src('src/app/**/*.html')
.pipe(ngHtml2Js({
moduleName: 'templates-main',
prefix: 'app/'
}))
.pipe(concat('templates.js'))
.pipe(gulp.dest('generated'))
);
// Build monolithic combined JavaScript source containing all pre-cached
// templates and all AngularJS module declarations in the proper order
gulp.task('build-combined-js',
() => gulp.src([
'src/app/**/*.js',
'generated/templates.js'
])
.pipe(angularFilesort())
.pipe(sourcemaps.init())
.pipe(concat('guacamole.js'))
.pipe(sourcemaps.write('./'))
.pipe(gulp.dest('generated'))
);
// Process monolithic JavaScript source through WebPack to produce a bundle
// that contains all required dependencies
gulp.task('build-webpack-bundle',
() => gulp.src('generated/guacamole.js')
.pipe(webpack(require('./webpack.config.js')))
.pipe(gulp.dest('dist'))
);
// Build all JavaScript for the entire application
gulp.task('build-js', gulp.series(
'build-template-js',
'build-combined-js',
'build-webpack-bundle'
));
// Copy plain, static contents of application
gulp.task('copy-static',
() => gulp.src([
'src/relocateParameters.js',
'src/index.html',
'src/fonts/**/*',
'src/images/**/*',
'src/layouts/**/*',
'src/translations/**/*'
], { base: './src' })
.pipe(gulp.dest('dist'))
);
gulp.task('default', gulp.series(
'clean',
gulp.parallel('build-css', 'build-js', 'copy-static')
));

File diff suppressed because it is too large Load Diff

View File

@@ -1,12 +1,13 @@
{
"private": true,
"scripts": {
"build": "gulp"
"build": "webpack --progress"
},
"dependencies": {
"@simonwep/pickr": "1.2.6",
"angular": "1.6.9",
"angular-route": "1.6.9",
"angular-templatecache-webpack-plugin": "^1.0.1",
"angular-touch": "1.6.9",
"angular-translate": "2.16.0",
"angular-translate-interpolation-messageformat": "2.16.0",
@@ -20,17 +21,16 @@
"messageformat": "1.0.2"
},
"devDependencies": {
"clean-webpack-plugin": "^3.0.0",
"closure-webpack-plugin": "^2.5.0",
"del": "^6.0.0",
"copy-webpack-plugin": "^5.1.2",
"css-loader": "^5.2.0",
"css-minimizer-webpack-plugin": "^1.3.0",
"exports-loader": "^1.1.1",
"google-closure-compiler": "^20210302.0.0",
"gulp": "^4.0.2",
"gulp-angular-filesort": "^1.2.1",
"gulp-clean-css": "^4.3.0",
"gulp-concat": "^2.6.1",
"gulp-ng-html2js": "^0.2.3",
"gulp-sourcemaps": "^3.0.0",
"source-map-loader": "^1.1.3",
"html-webpack-plugin": "^4.5.2",
"mini-css-extract-plugin": "^1.4.0",
"webpack": "^4.46.0",
"webpack-stream": "^6.1.2"
"webpack-cli": "^4.6.0"
}
}

View File

@@ -0,0 +1,56 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2014 Jed Richards
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
(function(angular) {
'use strict';
if ( !angular ) {
throw new Error('angular-module-shim: Missing Angular');
}
var origFn = angular.module;
var hash = {};
angular.module = function(name,requires,configFn) {
var requires = requires || [];
var registered = hash[name];
var module;
if ( registered ) {
module = origFn(name);
module.requires.push.apply(module.requires,requires);
// Register the config function if it exists.
if (configFn) {
module.config(configFn);
}
} else {
hash[name] = true;
module = origFn(name,requires,configFn);
}
return module;
};
})(window.angular);

View File

@@ -17,6 +17,8 @@
* under the License.
*/
import '@simonwep/pickr/dist/themes/monolith.min.css'
/**
* A service for prompting the user to choose a color using the "Pickr" color
* picker. As the Pickr color picker might not be available if the JavaScript

View File

@@ -17,10 +17,21 @@
* under the License.
*/
require('angular-module-shim.js');
require('relocateParameters.js');
require('angular-translate-interpolation-messageformat');
require('angular-translate-loader-static-files');
/**
* The module for the root of the application.
*/
angular.module('index', [
require('angular-route'),
require('angular-touch'),
require('angular-translate'),
'auth',
'client',
'clipboard',
@@ -28,11 +39,16 @@ angular.module('index', [
'login',
'manage',
'navigation',
'ngRoute',
'ngTouch',
'notification',
'pascalprecht.translate',
'rest',
'settings',
'templates-main'
]);
// Recursively pull in all other JavaScript and CSS files as requirements (just
// like old minify-maven-plugin build)
const context = require.context('../', true, /.*\.(css|js)$/);
context.keys().forEach(key => context(key));

View File

@@ -20,7 +20,7 @@
/**
* Provides the ClientIdentifier class definition.
*/
angular.module('client').factory('ClientIdentifier', ['$injector',
angular.module('navigation').factory('ClientIdentifier', ['$injector',
function defineClientIdentifier($injector) {
// Required services

View File

@@ -27,8 +27,15 @@
<link rel="icon" type="image/png" href="images/logo-64.png"/>
<link rel="icon" type="image/png" sizes="144x144" href="images/logo-144.png"/>
<link rel="apple-touch-icon" type="image/png" href="images/logo-144.png"/>
<link rel="stylesheet" type="text/css" href="guacamole.min.css?v=${project.version}">
<!-- Web application CSS (bundled by Webpack) -->
<% for (var index in htmlWebpackPlugin.files.css) { %>
<link rel="stylesheet" type="text/css" href="<%= htmlWebpackPlugin.files.css[index] %>"/>
<% } %>
<!-- Extension CSS (must be able to override webapp CSS) -->
<link rel="stylesheet" type="text/css" href="app.css?v=${project.version}">
<title ng-bind="page.title | translate"></title>
</head>
<body ng-class="page.bodyClassName">
@@ -68,11 +75,20 @@
</div>
</div>
<!-- Reformat URL for AngularJS if query parameters are present -->
<script type="text/javascript" src="relocateParameters.js"></script>
<!-- Core libraries that MUST be available at the global level (for use
by extensions) -->
<script type="text/javascript" src="guacamole-common-js/all.min.js"></script>
<script type="text/javascript" src="jquery.min.js"></script>
<script type="text/javascript" src="lodash.min.js"></script>
<script type="text/javascript" src="angular.min.js"></script>
<!-- Web application -->
<script type="text/javascript" src="guacamole.min.js?v=${project.version}"></script>
<!-- Web application (bundled by Webpack) -->
<% for (var index in htmlWebpackPlugin.files.js) { %>
<script type="text/javascript" src="<%= htmlWebpackPlugin.files.js[index] %>"></script>
<% } %>
<script type="text/javascript" src="templates.js"></script>
<!-- Extension JavaScript -->
<script type="text/javascript" src="app.js?v=${project.version}"></script>
</body>

View File

@@ -17,54 +17,150 @@
* under the License.
*/
const webpack = require('webpack');
const AngularTemplateCacheWebpackPlugin = require('angular-templatecache-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const ClosureWebpackPlugin = require('closure-webpack-plugin');
const CopyPlugin = require('copy-webpack-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const webpack = require('webpack');
module.exports = {
bail: true,
mode: 'production',
stats: 'minimal',
output: {
path: __dirname + '/dist',
filename: 'guacamole.min.js'
filename: 'guacamole.[contenthash].js',
},
// Generate source maps, automatically building off any source maps
// generated by Gulp
// Generate source maps
devtool: 'source-map',
// Entry point for the Guacamole webapp is the "index" AngularJS module
entry: './src/app/index/indexModule.js',
module: {
rules: [
// Automatically extract imported CSS for later reference within separate CSS file
{
test: /\.js$/,
enforce: 'pre',
use: [ 'source-map-loader' ]
test: /\.css$/i,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
import: false,
url: false
}
}
]
},
/*
* Necessary to be able to use angular 1 with webpack as explained in https://github.com/webpack/webpack/issues/2049
*/
{
test: require.resolve('angular'),
loader: 'exports-loader',
options: {
type: 'commonjs',
exports: 'single window.angular'
}
}
]
},
optimization: {
minimizer: [
// Automatically require used modules
// Minify using Google Closure Compiler
new ClosureWebpackPlugin({ mode: 'STANDARD' }, {
languageIn: 'ECMASCRIPT6',
languageOut: 'ECMASCRIPT5',
compilationLevel: 'SIMPLE'
}),
new CssMinimizerPlugin()
],
splitChunks: {
cacheGroups: {
// Bundle CSS as one file
styles: {
name: 'styles',
test: /\.css$/,
chunks: 'all',
enforce: true
}
}
}
},
plugins: [
new AngularTemplateCacheWebpackPlugin({
module: 'templates-main',
root: 'app/',
source: 'src/app/**/*.html',
standalone: true
}),
// Automatically clean out dist/ directory
new CleanWebpackPlugin(),
// Copy static files to dist/
new CopyPlugin([
{ from: 'fonts/**/*' },
{ from: 'images/**/*' },
{ from: 'translations/**/*' }
], {
context: 'src/'
}),
// Copy core libraries for global inclusion
new CopyPlugin([
{ from: 'angular/angular.min.js' },
{ from: 'jquery/dist/jquery.min.js' },
{ from: 'lodash/lodash.min.js' }
], {
context: 'node_modules/'
}),
// Generate index.html from template
new HtmlWebpackPlugin({
inject: false,
template: 'src/index.html'
}),
// Extract CSS from Webpack bundle as separate file
new MiniCssExtractPlugin({
filename: 'guacamole.[contenthash].css',
chunkFilename: '[id].guacamole.[contenthash].css'
}),
// Automatically require used modules
new webpack.ProvidePlugin({
$: 'jquery',
_: 'lodash',
angular: 'angular',
jstz: 'jstz',
Pickr: '@simonwep/pickr',
saveAs: 'file-saver'
})
],
// Minify using Google Closure Compiler
optimization: {
minimizer: [
new ClosureWebpackPlugin({ mode: 'STANDARD' }, {
externs: 'externs.js',
languageIn: 'ECMASCRIPT6',
languageOut: 'ECMASCRIPT5',
compilationLevel: 'ADVANCED'
})
],
resolve: {
// Include Node modules and base source tree within search path for
// import/resolve
modules: [
'src',
'node_modules'
]
}
};