diff options
Diffstat (limited to 'webpack.common.js')
-rw-r--r-- | webpack.common.js | 166 |
1 files changed, 147 insertions, 19 deletions
diff --git a/webpack.common.js b/webpack.common.js index c8bcb740236..80b0e0838e7 100644 --- a/webpack.common.js +++ b/webpack.common.js @@ -1,10 +1,25 @@ +/* eslint-disable n/no-extraneous-require */ /* eslint-disable camelcase */ +/** + * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ const { VueLoaderPlugin } = require('vue-loader') +const { readFileSync } = require('fs') const path = require('path') + const BabelLoaderExcludeNodeModulesExcept = require('babel-loader-exclude-node-modules-except') -const ESLintPlugin = require('eslint-webpack-plugin') const webpack = require('webpack') +const NodePolyfillPlugin = require('node-polyfill-webpack-plugin') +const WorkboxPlugin = require('workbox-webpack-plugin') +const WebpackSPDXPlugin = require('./build/WebpackSPDXPlugin.js') + const modules = require('./webpack.modules.js') +const { codecovWebpackPlugin } = require('@codecov/webpack-plugin') + +const appVersion = readFileSync('./version.php').toString().match(/OC_Version.+\[([0-9]{2})/)?.[1] ?? 'unknown' +const isDev = process.env.NODE_ENV === 'development' +const isTesting = process.env.TESTING === "true" const formatOutputFromModules = (modules) => { // merge all configs into one object, and use AppID to generate the fileNames @@ -24,7 +39,7 @@ const formatOutputFromModules = (modules) => { } const modulesToBuild = () => { - const MODULE = process.env.MODULE + const MODULE = process?.env?.MODULE if (MODULE) { if (!modules[MODULE]) { throw new Error(`No module "${MODULE}" found`) @@ -37,7 +52,7 @@ const modulesToBuild = () => { return formatOutputFromModules(modules) } -module.exports = { +const config = { entry: modulesToBuild(), output: { // Step away from the src folder and extract to the js folder @@ -50,11 +65,13 @@ module.exports = { // leak local paths https://github.com/webpack/webpack/issues/3603 devtoolNamespace: 'nextcloud', devtoolModuleFilenameTemplate(info) { - const rootDir = process.cwd() + const rootDir = process?.cwd() const rel = path.relative(rootDir, info.absoluteResourcePath) return `webpack:///nextcloud/${rel}` }, - clean: true, + clean: { + keep: /icons\.css/, // Keep static icons css + }, }, module: { @@ -84,6 +101,20 @@ module.exports = { ]), }, { + test: /\.tsx?$/, + use: [ + 'babel-loader', + { + // Fix TypeScript syntax errors in Vue + loader: 'ts-loader', + options: { + transpileOnly: true, + }, + }, + ], + exclude: BabelLoaderExcludeNodeModulesExcept([]), + }, + { test: /\.js$/, loader: 'babel-loader', // automatically detect necessary packages to @@ -91,7 +122,6 @@ module.exports = { exclude: BabelLoaderExcludeNodeModulesExcept([ '@nextcloud/dialogs', '@nextcloud/event-bus', - '@nextcloud/vue-dashboard', 'davclient.js', 'nextcloud-vue-collections', 'p-finally', @@ -115,18 +145,21 @@ module.exports = { test: /\.handlebars/, loader: 'handlebars-loader', }, - + { + resourceQuery: /raw/, + type: 'asset/source', + }, ], }, optimization: { splitChunks: { automaticNameDelimiter: '-', + minChunks: 3, // minimum number of chunks that must share the module cacheGroups: { vendors: { // split every dependency into one bundle test: /[\\/]node_modules[\\/]/, - enforce: true, // necessary to keep this name to properly inject it // see OC_Template.php name: 'core-common', @@ -138,27 +171,122 @@ module.exports = { plugins: [ new VueLoaderPlugin(), - new ESLintPlugin(), + new NodePolyfillPlugin({ + additionalAliases: ['process'], + }), new webpack.ProvidePlugin({ // Provide jQuery to jquery plugins as some are loaded before $ is exposed globally. - jQuery: 'jquery', - // Shim ICAL to prevent using the global object (window.ICAL). - // The library ical.js heavily depends on instanceof checks which will - // break if two separate versions of the library are used (e.g. bundled one - // and global one). - ICAL: 'ical.js', + // We need to provide the path to node_moduels as otherwise npm link will fail due + // to tribute.js checking for jQuery in @nextcloud/vue + jQuery: path.resolve(path.join(__dirname, 'node_modules/jquery')), + }), + + new WorkboxPlugin.GenerateSW({ + swDest: 'preview-service-worker.js', + clientsClaim: true, + skipWaiting: true, + exclude: [/.*/], // don't do pre-caching + inlineWorkboxRuntime: true, + sourcemap: false, + + // Increase perfs with less logging + disableDevLogs: true, + + // Define runtime caching rules. + runtimeCaching: [{ + // Match any preview file request + // /apps/files_trashbin/preview?fileId=156380&a=1 + // /core/preview?fileId=155842&a=1 + urlPattern: /^.*\/(apps|core)(\/[a-z-_]+)?\/preview.*/i, + + // Apply a strategy. + handler: 'CacheFirst', + + options: { + // Use a custom cache name. + cacheName: 'previews', + + // Only cache 10000 images. + expiration: { + maxAgeSeconds: 3600 * 24 * 7, // one week + maxEntries: 10000, + }, + }, + }], + }), + + // Make appName & appVersion available as a constants for '@nextcloud/vue' components + new webpack.DefinePlugin({ appName: JSON.stringify('Nextcloud') }), + new webpack.DefinePlugin({ appVersion: JSON.stringify(appVersion) }), + + // @nextcloud/moment since v1.3.0 uses `moment/min/moment-with-locales.js` + // Which works only in Node.js and is not compatible with Webpack bundling + // It has an unused function `localLocale` that requires locales by invalid relative path `./locale` + // Though it is not used, Webpack tries to resolve it with `require.context` and fails + new webpack.IgnorePlugin({ + resourceRegExp: /^\.\/locale$/, + contextRegExp: /moment\/min$/, + }), + codecovWebpackPlugin({ + enableBundleAnalysis: !isDev && !isTesting, + bundleName: 'nextcloud', + telemetry: false, }), ], + externals: { + OC: 'OC', + OCA: 'OCA', + OCP: 'OCP', + }, resolve: { alias: { // make sure to use the handlebar runtime when importing handlebars: 'handlebars/runtime', + vue$: path.resolve('./node_modules/vue'), }, - extensions: ['*', '.js', '.vue'], - symlinks: false, + extensions: ['*', '.ts', '.js', '.vue'], + extensionAlias: { + /** + * Resolve TypeScript files when using fully-specified esm import paths + * https://github.com/webpack/webpack/issues/13252 + */ + '.js': ['.js', '.ts'], + }, + symlinks: true, fallback: { - stream: require.resolve('stream-browserify'), - buffer: require.resolve('buffer'), + fs: false, }, }, } + +// Generate reuse license files if not in development mode +if (!isDev) { + config.plugins.push(new WebpackSPDXPlugin({ + override: { + select2: 'MIT', + '@nextcloud/axios': 'GPL-3.0-or-later', + '@nextcloud/vue': 'AGPL-3.0-or-later', + 'nextcloud-vue-collections': 'AGPL-3.0-or-later', + }, + })) + + config.optimization.minimizer = [{ + apply: (compiler) => { + // Lazy load the Terser plugin + const TerserPlugin = require('terser-webpack-plugin') + new TerserPlugin({ + extractComments: false, + terserOptions: { + format: { + comments: false, + }, + compress: { + passes: 2, + }, + }, + }).apply(compiler) + }, + }] +} + +module.exports = config |