Update to Webpack 5 and redesign build process.

This commit is contained in:
Buster "Silver Eagle" Neece 2021-09-11 15:46:31 -05:00
parent 2e98b94685
commit 8272aa5ef9
No known key found for this signature in database
GPG Key ID: 6D9E12FF03411F4E
11 changed files with 1820 additions and 11887 deletions

3
.gitignore vendored
View File

@ -34,6 +34,9 @@ tmp/cache/*---*
/web/static/dist/*
/web/static/dist/**/*
!/web/static/dist/.gitkeep
/web/static/webpack_dist/*
/web/static/webpack_dist/**/*
!/web/static/webpack_dist/.gitkeep
/web/static/assets.json
/web/static/webpack.json

View File

@ -42,22 +42,6 @@ return [
],
],
'vue-base' => [
'order' => 5,
'files' => [
'js' => [
[
'src' => 'dist/VueBase.js',
],
],
],
'inline' => [
'js' => [
'VueBase.default()',
],
],
],
'bootstrap-vue' => [
'order' => 4,
'files' => [
@ -74,29 +58,6 @@ return [
],
],
'vue-component-common' => [
'order' => 4,
'require' => ['vue', 'vue-base'],
'files' => [
'js' => [
[
'src' => 'dist/vendor.js',
],
],
],
],
'lodash' => [
'order' => 2,
'files' => [
'js' => [
[
'src' => 'dist/lib/lodash/lodash.min.js',
],
],
],
],
/*
* Main per-layout dependencies
*/
@ -450,81 +411,68 @@ return [
],
],
'leaflet' => [
'order' => 20,
'files' => [
'Vue_Base' => [
'order' => 5,
'require' => ['vue'],
// Auto-managed by Assets
'inline' => [
'js' => [
[
'src' => 'dist/lib/leaflet/leaflet.js',
'defer' => true,
],
[
'src' => 'dist/lib/leaflet-fullscreen/Control.FullScreen.js',
'defer' => true,
],
],
'css' => [
[
'href' => 'dist/lib/leaflet/leaflet.css',
],
[
'href' => 'dist/lib/leaflet-fullscreen/Control.FullScreen.css',
],
'Base.default()',
],
],
],
'Vue_Dashboard' => [
'order' => 10,
'require' => ['vue-component-common', 'uses-api', 'bootstrap-vue', 'chartjs'],
'require' => ['Vue_Base', 'bootstrap-vue', 'uses-api', 'chartjs'],
// Auto-managed by Assets
],
'Vue_PublicFullPlayer' => [
'order' => 10,
'require' => ['vue-component-common', 'bootstrap-vue', 'moment', 'fancybox'],
'require' => ['Vue_Base', 'bootstrap-vue', 'moment', 'fancybox'],
// Auto-managed by Assets
],
'Vue_PublicHistory' => [
'order' => 10,
'require' => ['vue-component-common', 'bootstrap-vue', 'moment'],
'require' => ['Vue_Base', 'bootstrap-vue', 'moment'],
// Auto-managed by Assets
],
'Vue_AdminBranding' => [
'order' => 10,
'require' => ['vue-component-common', 'uses-api', 'bootstrap-vue', 'fancybox', 'codemirror'],
'require' => ['Vue_Base', 'bootstrap-vue', 'uses-api', 'fancybox', 'codemirror'],
// Auto-managed by Assets
],
'Vue_AdminStorageLocations' => [
'order' => 10,
'require' => ['vue-component-common', 'uses-api', 'bootstrap-vue'],
'require' => ['Vue_Base', 'bootstrap-vue', 'uses-api'],
// Auto-managed by Assets
],
'Vue_PublicOnDemand' => [
'order' => 10,
'require' => ['vue-component-common', 'bootstrap-vue'],
'require' => ['Vue_Base', 'bootstrap-vue'],
// Auto-managed by Assets
],
'Vue_PublicRequests' => [
'order' => 10,
'require' => ['vue-component-common', 'bootstrap-vue'],
'require' => ['Vue_Base', 'bootstrap-vue'],
// Auto-managed by Assets
],
'Vue_PublicSchedule' => [
'order' => 10,
'require' => ['vue-component-common', 'bootstrap-vue', 'moment_timezone'],
'require' => ['Vue_Base', 'bootstrap-vue', 'moment_timezone'],
// Auto-managed by Assets
],
'Vue_PublicWebDJ' => [
'order' => 10,
'require' => ['vue-component-common'],
'require' => ['Vue_Base'],
'files' => [
'js' => [
[
@ -545,67 +493,73 @@ return [
'Vue_StationsMedia' => [
'order' => 10,
'require' => ['vue-component-common', 'uses-api', 'bootstrap-vue', 'fancybox'],
'require' => ['Vue_Base', 'uses-api', 'bootstrap-vue', 'fancybox'],
// Auto-managed by Assets
],
'Vue_StationsMounts' => [
'order' => 10,
'require' => ['vue-component-common', 'uses-api', 'bootstrap-vue'],
'require' => ['Vue_Base', 'uses-api', 'bootstrap-vue'],
// Auto-managed by Assets
],
'Vue_StationsPlaylists' => [
'order' => 10,
'require' => ['vue-component-common', 'uses-api', 'bootstrap-vue', 'moment_timezone'],
'require' => ['Vue_Base', 'uses-api', 'bootstrap-vue', 'moment_timezone'],
// Auto-managed by Assets
],
'Vue_StationsPodcasts' => [
'order' => 10,
'require' => ['vue-component-common', 'uses-api', 'bootstrap-vue', 'fancybox', 'moment_timezone'],
'require' => ['Vue_Base', 'uses-api', 'bootstrap-vue', 'fancybox', 'moment_timezone'],
// Auto-managed by Assets
],
'Vue_StationsPodcastEpisodes' => [
'order' => 10,
'require' => ['vue-component-common', 'uses-api', 'bootstrap-vue', 'fancybox', 'moment_timezone'],
'require' => ['Vue_Base', 'uses-api', 'bootstrap-vue', 'fancybox', 'moment_timezone'],
// Auto-managed by Assets
],
'Vue_StationsProfile' => [
'order' => 10,
'require' => ['vue-component-common', 'uses-api', 'bootstrap-vue', 'moment', 'fancybox'],
'require' => ['Vue_Base', 'uses-api', 'bootstrap-vue', 'moment', 'fancybox'],
// Auto-managed by Assets
],
'Vue_StationsQueue' => [
'order' => 10,
'require' => ['vue-component-common', 'uses-api', 'bootstrap-vue', 'moment'],
'require' => ['Vue_Base', 'uses-api', 'bootstrap-vue', 'moment'],
// Auto-managed by Assets
],
'Vue_StationsRemotes' => [
'order' => 10,
'require' => ['vue-component-common', 'uses-api', 'bootstrap-vue'],
'require' => ['Vue_Base', 'uses-api', 'bootstrap-vue'],
// Auto-managed by Assets
],
'Vue_StationsStreamers' => [
'order' => 10,
'require' => ['vue-component-common', 'uses-api', 'bootstrap-vue', 'moment'],
'require' => ['Vue_Base', 'uses-api', 'bootstrap-vue', 'moment'],
// Auto-managed by Assets
],
'Vue_StationsReportsListeners' => [
'order' => 10,
'require' => ['Vue_Base', 'uses-api', 'bootstrap-vue', 'moment'],
// Auto-managed by Assets
],
'Vue_StationsReportsRequests' => [
'order' => 10,
'require' => ['vue-component-common', 'uses-api', 'bootstrap-vue', 'moment'],
'require' => ['Vue_Base', 'uses-api', 'bootstrap-vue', 'moment'],
// Auto-managed by Assets
],
'Vue_StationsReportsOverview' => [
'order' => 10,
'require' => ['vue-component-common', 'uses-api', 'bootstrap-vue', 'chartjs'],
'require' => ['Vue_Base', 'uses-api', 'bootstrap-vue', 'chartjs'],
// Auto-managed by Assets
],
];

View File

@ -10,9 +10,8 @@ const sourcemaps = require('gulp-sourcemaps');
const sass = require('gulp-dart-sass');
const clean_css = require('gulp-clean-css');
const revdel = require('gulp-rev-delete-original');
const webpackStream = require('webpack-stream');
const gulpIgnore = require('gulp-ignore');
const mode = require('gulp-mode')();
const run = require('gulp-run-command').default;
var jsFiles = {
// Core Libraries
@ -81,12 +80,6 @@ var jsFiles = {
},
// Individual libraries
'store': {
base: 'node_modules/store',
files: [
'node_modules/store/store.min.js'
]
},
'zxcvbn': {
base: 'node_modules/zxcvbn/dist',
files: [
@ -148,28 +141,6 @@ var jsFiles = {
'node_modules/@fancyapps/fancybox/dist/jquery.fancybox.min.*'
]
},
'flowjs': {
base: 'node_modules/@flowjs/flow.js/dist',
files: [
'node_modules/@flowjs/flow.js/dist/flow.min.js'
]
},
'leaflet': {
base: 'node_modules/leaflet/dist',
files: [
'node_modules/leaflet/dist/leaflet.js',
'node_modules/leaflet/dist/leaflet.css',
'node_modules/leaflet/dist/images/*'
]
},
'leaflet-fullscreen': {
base: 'node_modules/leaflet.fullscreen',
files: [
'node_modules/leaflet.fullscreen/Control.FullScreen.js',
'node_modules/leaflet.fullscreen/Control.FullScreen.css',
'node_modules/leaflet.fullscreen/icon-*.png'
]
},
'nchan': {
base: null,
files: [
@ -217,6 +188,7 @@ gulp.task('bundle_deps', gulp.parallel(
gulp.task('clean', function () {
return del([
'../web/static/dist/**/*',
'../web/static/webpack_dist/**/*',
'../web/static/assets.json',
'../web/static/webpack.json'
], { force: true });
@ -234,16 +206,7 @@ gulp.task('concat-js', function () {
.pipe(gulp.dest('../web/static/dist'));
});
gulp.task('build-vue', function () {
return gulp.src(['vue/*.js', 'vue/*.vue'])
.pipe(webpackStream(require('./webpack.config.js')))
.pipe(gulpIgnore.exclude('webpack.json'))
.pipe(babel({
presets: ['@babel/env']
}))
.pipe(uglify())
.pipe(gulp.dest('../web/static/dist'));
});
gulp.task('build-vue', run('webpack -c webpack.config.js'));
gulp.task('build-js', function () {
return gulp.src(['./js/*.js'])

File diff suppressed because it is too large Load Diff

View File

@ -10,8 +10,8 @@
"ci": "npm run import-locales && npm run build"
},
"dependencies": {
"@babel/core": "^7.13.16",
"@babel/preset-env": "^7.13.15",
"@babel/core": "^7.15.5",
"@babel/preset-env": "^7.15.6",
"@fancyapps/fancybox": "^3.5.7",
"@flowjs/flow.js": "^2.14.1",
"@fullcalendar/core": "^4",
@ -21,7 +21,7 @@
"@fullcalendar/timegrid": "^4",
"@fullcalendar/vue": "^4",
"autosize": "^4.0.2",
"axios": "^0.21.1",
"axios": "^0.21.4",
"bootstrap": "^4.6.0",
"bootstrap-daterangepicker": "^3.1.0",
"bootstrap-notify": "^3.1.3",
@ -30,7 +30,7 @@
"chartjs-plugin-colorschemes": "^0.3.0",
"chartjs-plugin-zoom": "^0.7.7",
"clipboard": "^2.0.8",
"codemirror": "^5.61.0",
"codemirror": "^5.62.3",
"css-loader": "^1.0",
"del": "^3.0.0",
"dirrty": "^1.0.0",
@ -40,10 +40,10 @@
"gulp-clean-css": "^3.9.2",
"gulp-concat": "^2.6.1",
"gulp-dart-sass": "^1.0.2",
"gulp-ignore": "^3.0.0",
"gulp-mode": "^1.1.0",
"gulp-rev": "^8.1.1",
"gulp-rev-delete-original": "^0.2.3",
"gulp-run-command": "0.0.10",
"gulp-sourcemaps": "^2.6.5",
"gulp-uglify": "^3.0.2",
"jquery": "^3.6.0",
@ -57,23 +57,26 @@
"popper.js": "^1.16.1",
"prettier": "1.12.1",
"roboto-fontface": "^0.10.0",
"sass": "^1.32.12",
"sass": "^1.39.2",
"sass-loader": "^7.3.1",
"select2": "^4.0.13",
"sortablejs": "^1.13.0",
"sortablejs": "^1.14.0",
"store": "^1.3.20",
"sweetalert2": "^10.16.6",
"vue": "^2.6.12",
"vue-axios": "^3.2.5",
"vue": "^2.6.14",
"vue-axios": "^3.3.6",
"vue-gettext": "^2.1.12",
"vue-loader": "14.2.2",
"vue-template-compiler": "^2.6.12",
"vue-loader": "^15.9.8",
"vue-template-compiler": "^2.6.14",
"vue2-daterange-picker": "^0.6.6",
"vue2-leaflet": "^2.7.1",
"vue2-leaflet-fullscreen": "^1.0.1",
"vuedraggable": "^2.24.1",
"vuelidate": "^0.7.5",
"vuelidate": "^0.7.6",
"wavesurfer.js": "^3.3.3",
"webpack": "^4.46.0",
"webpack": "^5.52.1",
"webpack-assets-manifest": "^3.1.1",
"webpack-stream": "^5.1.1",
"webpack-cli": "^4.8.0",
"zxcvbn": "^4.4.2"
}
}

View File

@ -7,7 +7,7 @@ import GetTextPlugin
import translations
from '../../resources/locale/translations';
export default function (lang, csrf) {
export default function () {
// Configure localization
Vue.use(GetTextPlugin, {
defaultLanguage: 'en_US',

View File

@ -1,10 +1,12 @@
const webpack = require('webpack');
const WebpackAssetsManifest = require('webpack-assets-manifest');
const { VueLoaderPlugin } = require('vue-loader');
const path = require('path');
module.exports = {
mode: 'production',
mode: 'development',
entry: {
VueBase: './vue/VueBase.js',
Base: './vue/VueBase.js',
InlinePlayer: './vue/InlinePlayer.vue',
Dashboard: './vue/Dashboard.vue',
AdminBranding: './vue/Admin/Branding.vue',
@ -24,17 +26,21 @@ module.exports = {
StationsQueue: './vue/Stations/Queue.vue',
StationsRemotes: './vue/Stations/Remotes.vue',
StationsStreamers: './vue/Stations/Streamers.vue',
StationsReportsListeners: './vue/Stations/Reports/Listeners.vue',
StationsReportsRequests: './vue/Stations/Reports/Requests.vue',
StationsReportsOverview: './vue/Stations/Reports/Overview.vue'
},
resolve: {
extensions: ['*', '.js', '.vue', '.json']
enforceExtension: false,
extensions: ['.js', '.vue', '.json']
},
output: {
publicPath: 'dist/',
filename: '[name].js',
sourceMapFilename: '[name].map',
library: '[name]'
path: path.resolve(__dirname, '../web/static/webpack_dist'),
publicPath: '/static/webpack_dist/',
filename: '[name].[contenthash].js',
sourceMapFilename: '[name].[contenthash].map',
library: '[name]',
assetModuleFilename: 'images/[contenthash][ext]'
},
optimization: {
splitChunks: {
@ -53,6 +59,20 @@ module.exports = {
chunks: 'initial',
enforce: true
},
leaflet: {
test: /[\\/]node_modules[\\/]leaflet/,
name: 'vendor-leaflet',
priority: 2,
chunks: 'initial',
enforce: true
},
vuelidate: {
test: /[\\/]node_modules[\\/]vuelidate/,
name: 'vendor-vuelidate',
priority: 2,
chunks: 'initial',
enforce: true
},
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendor',
@ -65,24 +85,43 @@ module.exports = {
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader'
test: /\.vue$/i,
use: [
'vue-loader'
]
},
{
test: /\.scss$/,
loader: 'vue-style-loader'
test: /\.scss$/i,
use: [
'vue-style-loader',
'css-loader',
'sass-loader'
]
},
{
test: /\.css$/i,
use: [
'vue-style-loader',
'css-loader'
]
},
{
test: /\.(png|jpe?g|gif|svg|eot|ttf|woff|woff2)$/i,
type: 'asset/resource'
}
]
},
plugins: [
new WebpackAssetsManifest({
output: '../web/static/webpack.json',
output: path.resolve(__dirname, '../web/static/webpack.json'),
writeToDisk: true,
merge: true,
publicPath: true,
entrypoints: true
})
}),
new VueLoaderPlugin()
],
target: 'web',
performance: {
hints: false
}

View File

@ -73,16 +73,14 @@ class Assets
'files' => [],
];
if (!in_array('vue-component-common', $library['require'], true)) {
$library['require'][] = 'vue-component-common';
if ($componentName !== 'Vue_Base' && !in_array('Vue_Base', $library['require'], true)) {
$library['require'][] = 'Vue_Base';
}
foreach ($componentDeps['js'] as $componentDep) {
if ('dist/vendor.js' !== $componentDep) {
$library['files']['js'][] = [
'src' => $componentDep,
];
}
$library['files']['js'][] = [
'src' => $componentDep,
];
}
$this->addLibrary($library, $componentName);
@ -330,7 +328,7 @@ class Assets
foreach ($this->loaded as $item) {
if (!empty($item['files']['css'])) {
foreach ($item['files']['css'] as $file) {
$compiled_attributes = $this->compileAttributes(
$attributes = $this->resolveAttributes(
$file,
[
'rel' => 'stylesheet',
@ -338,7 +336,12 @@ class Assets
]
);
$result[] = '<link ' . implode(' ', $compiled_attributes) . ' />';
$key = $attributes['href'];
if (isset($result[$key])) {
continue;
}
$result[$key] = '<link ' . implode(' ', $this->compileAttributes($attributes)) . ' />';
}
}
@ -372,14 +375,19 @@ class Assets
foreach ($this->loaded as $item) {
if (!empty($item['files']['js'])) {
foreach ($item['files']['js'] as $file) {
$compiled_attributes = $this->compileAttributes(
$attributes = $this->resolveAttributes(
$file,
[
'type' => 'text/javascript',
]
);
$result[] = '<script ' . implode(' ', $compiled_attributes) . '></script>';
$key = $attributes['src'];
if (isset($result[$key])) {
continue;
}
$result[$key] = '<script ' . implode(' ', $this->compileAttributes($attributes)) . '></script>';
}
}
}
@ -434,15 +442,7 @@ class Assets
}
}
/**
* Build the proper include tag for a JS/CSS include.
*
* @param array $file
* @param array $defaults
*
* @return string[]
*/
protected function compileAttributes(array $file, array $defaults = []): array
protected function resolveAttributes(array $file, array $defaults): array
{
if (isset($file['src'])) {
$defaults['src'] = $this->getUrl($file['src']);
@ -458,8 +458,18 @@ class Assets
$defaults['crossorigin'] = 'anonymous';
}
$attributes = array_merge($defaults, $file);
return array_merge($defaults, $file);
}
/**
* Build the proper include tag for a JS/CSS include.
*
* @param array $attributes
*
* @return string[]
*/
protected function compileAttributes(array $attributes): array
{
$compiled_attributes = [];
foreach ($attributes as $attr_key => $attr_val) {
// Check for attributes like "defer"
@ -520,6 +530,10 @@ class Assets
return $resource_uri;
}
if (str_starts_with($resource_uri, '/')) {
return $resource_uri;
}
return $this->environment->getAssetUrl() . '/' . $resource_uri;
}

View File

@ -72,6 +72,9 @@ server {
location /static/dist {
expires 365d;
}
location /static/webpack_dist {
expires 365d;
}
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;

View File

@ -109,6 +109,9 @@ server {
location /static/dist {
expires 365d;
}
location /static/webpack_dist {
expires 365d;
}
location ~ ^/index\.php(/|$) {
fastcgi_split_path_info ^(.+\.php)(/.+)$;

View File

@ -0,0 +1 @@
.gitkeep