diff --git a/.storybook/webpack.config.ts b/.storybook/webpack.config.ts index 2fdae76c1268..3b93756f1df5 100644 --- a/.storybook/webpack.config.ts +++ b/.storybook/webpack.config.ts @@ -31,49 +31,57 @@ switch (process.env.ENV) { } const env = dotenv.config({path: path.resolve(__dirname, `../${envFile}`)}); -const custom: CustomWebpackConfig = require('../config/webpack/webpack.common')({ +const custom: CustomWebpackConfig = require('../config/webpack/webpack.common').default({ envFile, }); const webpackConfig = ({config}: {config: Configuration}) => { - if (config.resolve && config.plugins && config.module) { - config.resolve.alias = { - 'react-native-config': 'react-web-config', - 'react-native$': 'react-native-web', - '@react-native-community/netinfo': path.resolve(__dirname, '../__mocks__/@react-native-community/netinfo.ts'), - '@react-navigation/native': path.resolve(__dirname, '../__mocks__/@react-navigation/native'), - ...custom.resolve.alias, - }; + if (!config.resolve) { + config.resolve = {}; + } + if (!config.plugins) { + config.plugins = []; + } + if (!config.module) { + config.module = {}; + } - // Necessary to overwrite the values in the existing DefinePlugin hardcoded to the Config staging values - const definePluginIndex = config.plugins.findIndex((plugin) => plugin instanceof DefinePlugin); - if (definePluginIndex !== -1 && config.plugins[definePluginIndex] instanceof DefinePlugin) { - const definePlugin = config.plugins[definePluginIndex] as DefinePlugin; - if (definePlugin.definitions) { - definePlugin.definitions.__REACT_WEB_CONFIG__ = JSON.stringify(env); - } - } - config.resolve.extensions = custom.resolve.extensions; + config.resolve.alias = { + 'react-native-config': 'react-web-config', + 'react-native$': 'react-native-web', + '@react-native-community/netinfo': path.resolve(__dirname, '../__mocks__/@react-native-community/netinfo.ts'), + '@react-navigation/native': path.resolve(__dirname, '../__mocks__/@react-navigation/native'), + ...custom.resolve.alias, + }; - const babelRulesIndex = custom.module.rules.findIndex((rule) => rule.loader === 'babel-loader'); - const babelRule = custom.module.rules[babelRulesIndex]; - if (babelRule) { - config.module.rules?.push(babelRule); + // Necessary to overwrite the values in the existing DefinePlugin hardcoded to the Config staging values + const definePluginIndex = config.plugins.findIndex((plugin) => plugin instanceof DefinePlugin); + if (definePluginIndex !== -1 && config.plugins[definePluginIndex] instanceof DefinePlugin) { + const definePlugin = config.plugins[definePluginIndex] as DefinePlugin; + if (definePlugin.definitions) { + definePlugin.definitions.__REACT_WEB_CONFIG__ = JSON.stringify(env); } + } + config.resolve.extensions = custom.resolve.extensions; - const fileLoaderRule = config.module.rules?.find( - (rule): rule is RuleSetRule => - typeof rule !== 'boolean' && typeof rule !== 'string' && typeof rule !== 'number' && !!rule?.test && rule.test instanceof RegExp && rule.test.test('.svg'), - ); - if (fileLoaderRule) { - fileLoaderRule.exclude = /\.svg$/; - } - config.module.rules?.push({ - test: /\.svg$/, - enforce: 'pre', - loader: require.resolve('@svgr/webpack'), - }); + const babelRulesIndex = custom.module.rules.findIndex((rule) => rule.loader === 'babel-loader'); + const babelRule = custom.module.rules[babelRulesIndex]; + if (babelRule) { + config.module.rules?.push(babelRule); + } + + const fileLoaderRule = config.module.rules?.find( + (rule): rule is RuleSetRule => + typeof rule !== 'boolean' && typeof rule !== 'string' && typeof rule !== 'number' && !!rule?.test && rule.test instanceof RegExp && rule.test.test('.svg'), + ); + if (fileLoaderRule) { + fileLoaderRule.exclude = /\.svg$/; } + config.module.rules?.push({ + test: /\.svg$/, + enforce: 'pre', + loader: require.resolve('@svgr/webpack'), + }); return config; }; diff --git a/README.md b/README.md index 7019567c7acb..026a63606db0 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ If you're using another operating system, you will need to ensure `mkcert` is in ## Running the web app 🕸 * To run the **development web app**: `npm run web` -* Changes applied to Javascript will be applied automatically via WebPack as configured in `webpack.dev.js` +* Changes applied to Javascript will be applied automatically via WebPack as configured in `webpack.dev.ts` ## Running the iOS app 📱 For an M1 Mac, read this [SO](https://stackoverflow.com/questions/64901180/how-to-run-cocoapods-on-apple-silicon-m1) for installing cocoapods. diff --git a/config/proxyConfig.js b/config/proxyConfig.ts similarity index 64% rename from config/proxyConfig.js rename to config/proxyConfig.ts index fa09c436461f..0fecef28c1cf 100644 --- a/config/proxyConfig.js +++ b/config/proxyConfig.ts @@ -3,7 +3,14 @@ * We only specify for staging URLs as API requests are sent to the production * servers by default. */ -module.exports = { +type ProxyConfig = { + STAGING: string; + STAGING_SECURE: string; +}; + +const proxyConfig: ProxyConfig = { STAGING: '/staging/', STAGING_SECURE: '/staging-secure/', }; + +export default proxyConfig; diff --git a/config/webpack/CustomVersionFilePlugin.js b/config/webpack/CustomVersionFilePlugin.js deleted file mode 100644 index ed7c0f3dca95..000000000000 --- a/config/webpack/CustomVersionFilePlugin.js +++ /dev/null @@ -1,33 +0,0 @@ -const fs = require('fs'); -const path = require('path'); -const APP_VERSION = require('../../package.json').version; - -/** - * Simple webpack plugin that writes the app version (from package.json) and the webpack hash to './version.json' - */ -class CustomVersionFilePlugin { - apply(compiler) { - compiler.hooks.done.tap( - this.constructor.name, - () => - new Promise((resolve, reject) => { - const versionPath = path.join(__dirname, '/../../dist/version.json'); - fs.mkdir(path.dirname(versionPath), {recursive: true}, (dirErr) => { - if (dirErr) { - reject(dirErr); - return; - } - fs.writeFile(versionPath, JSON.stringify({version: APP_VERSION}), 'utf8', (fileErr) => { - if (fileErr) { - reject(fileErr); - return; - } - resolve(); - }); - }); - }), - ); - } -} - -module.exports = CustomVersionFilePlugin; diff --git a/config/webpack/CustomVersionFilePlugin.ts b/config/webpack/CustomVersionFilePlugin.ts new file mode 100644 index 000000000000..96ab8e61e480 --- /dev/null +++ b/config/webpack/CustomVersionFilePlugin.ts @@ -0,0 +1,28 @@ +import fs from 'fs'; +import path from 'path'; +import type {Compiler} from 'webpack'; +import {version as APP_VERSION} from '../../package.json'; + +/** + * Simple webpack plugin that writes the app version (from package.json) and the webpack hash to './version.json' + */ +class CustomVersionFilePlugin { + apply(compiler: Compiler) { + compiler.hooks.done.tap(this.constructor.name, () => { + const versionPath = path.join(__dirname, '/../../dist/version.json'); + fs.mkdir(path.dirname(versionPath), {recursive: true}, (directoryError) => { + if (directoryError) { + throw directoryError; + } + fs.writeFile(versionPath, JSON.stringify({version: APP_VERSION}), {encoding: 'utf8'}, (error) => { + if (!error) { + return; + } + throw error; + }); + }); + }); + } +} + +export default CustomVersionFilePlugin; diff --git a/config/webpack/types.ts b/config/webpack/types.ts new file mode 100644 index 000000000000..45a81feb9bff --- /dev/null +++ b/config/webpack/types.ts @@ -0,0 +1,6 @@ +type Environment = { + file?: string; + platform?: 'web' | 'desktop'; +}; + +export default Environment; diff --git a/config/webpack/webpack.common.js b/config/webpack/webpack.common.ts similarity index 79% rename from config/webpack/webpack.common.js rename to config/webpack/webpack.common.ts index 2fed8a477aab..b0e301ef3a6c 100644 --- a/config/webpack/webpack.common.js +++ b/config/webpack/webpack.common.ts @@ -1,13 +1,17 @@ -const path = require('path'); -const fs = require('fs'); -const {IgnorePlugin, DefinePlugin, ProvidePlugin, EnvironmentPlugin} = require('webpack'); -const {CleanWebpackPlugin} = require('clean-webpack-plugin'); -const HtmlWebpackPlugin = require('html-webpack-plugin'); -const CopyPlugin = require('copy-webpack-plugin'); -const dotenv = require('dotenv'); -const {BundleAnalyzerPlugin} = require('webpack-bundle-analyzer'); +import {CleanWebpackPlugin} from 'clean-webpack-plugin'; +import CopyPlugin from 'copy-webpack-plugin'; +import dotenv from 'dotenv'; +import fs from 'fs'; +import HtmlWebpackPlugin from 'html-webpack-plugin'; +import path from 'path'; +import type {Configuration} from 'webpack'; +import {DefinePlugin, EnvironmentPlugin, IgnorePlugin, ProvidePlugin} from 'webpack'; +import {BundleAnalyzerPlugin} from 'webpack-bundle-analyzer'; +import CustomVersionFilePlugin from './CustomVersionFilePlugin'; +import type Environment from './types'; + +// require is necessary, there are no types for this package and the declaration file can't be seen by the build process which causes an error. const PreloadWebpackPlugin = require('@vue/preload-webpack-plugin'); -const CustomVersionFilePlugin = require('./CustomVersionFilePlugin'); const includeModules = [ 'react-native-animatable', @@ -25,29 +29,25 @@ const includeModules = [ 'expo-av', ].join('|'); -const envToLogoSuffixMap = { +const environmentToLogoSuffixMap: Record = { production: '', staging: '-stg', dev: '-dev', adhoc: '-adhoc', }; -function mapEnvToLogoSuffix(envFile) { - let env = envFile.split('.')[2]; - if (typeof env === 'undefined') { - env = 'dev'; +function mapEnvironmentToLogoSuffix(environmentFile: string): string { + let environment = environmentFile.split('.')[2]; + if (typeof environment === 'undefined') { + environment = 'dev'; } - return envToLogoSuffixMap[env]; + return environmentToLogoSuffixMap[environment]; } /** * Get a production grade config for web or desktop - * @param {Object} env - * @param {String} env.envFile path to the env file to be used - * @param {'web'|'desktop'} env.platform - * @returns {Configuration} */ -const webpackConfig = ({envFile = '.env', platform = 'web'}) => ({ +const getCommonConfiguration = ({file = '.env', platform = 'web'}: Environment): Configuration => ({ mode: 'production', devtool: 'source-map', entry: { @@ -68,10 +68,10 @@ const webpackConfig = ({envFile = '.env', platform = 'web'}) => ({ new HtmlWebpackPlugin({ template: 'web/index.html', filename: 'index.html', - splashLogo: fs.readFileSync(path.resolve(__dirname, `../../assets/images/new-expensify${mapEnvToLogoSuffix(envFile)}.svg`), 'utf-8'), + splashLogo: fs.readFileSync(path.resolve(__dirname, `../../assets/images/new-expensify${mapEnvironmentToLogoSuffix(file)}.svg`), 'utf-8'), isWeb: platform === 'web', - isProduction: envFile === '.env.production', - isStaging: envFile === '.env.staging', + isProduction: file === '.env.production', + isStaging: file === '.env.staging', }), new PreloadWebpackPlugin({ rel: 'preload', @@ -121,12 +121,14 @@ const webpackConfig = ({envFile = '.env', platform = 'web'}) => ({ ...(platform === 'web' ? [new CustomVersionFilePlugin()] : []), new DefinePlugin({ ...(platform === 'desktop' ? {} : {process: {env: {}}}), - __REACT_WEB_CONFIG__: JSON.stringify(dotenv.config({path: envFile}).parsed), + // eslint-disable-next-line @typescript-eslint/naming-convention + __REACT_WEB_CONFIG__: JSON.stringify(dotenv.config({path: file}).parsed), // React Native JavaScript environment requires the global __DEV__ variable to be accessible. // react-native-render-html uses variable to log exclusively during development. // See https://reactnative.dev/docs/javascript-environment - __DEV__: /staging|prod|adhoc/.test(envFile) === false, + // eslint-disable-next-line @typescript-eslint/naming-convention + __DEV__: /staging|prod|adhoc/.test(file) === false, }), // This allows us to interactively inspect JS bundle contents @@ -203,21 +205,34 @@ const webpackConfig = ({envFile = '.env', platform = 'web'}) => ({ }, resolve: { alias: { + // eslint-disable-next-line @typescript-eslint/naming-convention 'react-native-config': 'react-web-config', + // eslint-disable-next-line @typescript-eslint/naming-convention 'react-native$': 'react-native-web', + // eslint-disable-next-line @typescript-eslint/naming-convention 'react-native-sound': 'react-native-web-sound', // Module alias for web & desktop // https://webpack.js.org/configuration/resolve/#resolvealias + // eslint-disable-next-line @typescript-eslint/naming-convention '@assets': path.resolve(__dirname, '../../assets'), + // eslint-disable-next-line @typescript-eslint/naming-convention '@components': path.resolve(__dirname, '../../src/components/'), + // eslint-disable-next-line @typescript-eslint/naming-convention '@hooks': path.resolve(__dirname, '../../src/hooks/'), + // eslint-disable-next-line @typescript-eslint/naming-convention '@libs': path.resolve(__dirname, '../../src/libs/'), + // eslint-disable-next-line @typescript-eslint/naming-convention '@navigation': path.resolve(__dirname, '../../src/libs/Navigation/'), + // eslint-disable-next-line @typescript-eslint/naming-convention '@pages': path.resolve(__dirname, '../../src/pages/'), + // eslint-disable-next-line @typescript-eslint/naming-convention '@styles': path.resolve(__dirname, '../../src/styles/'), // This path is provide alias for files like `ONYXKEYS` and `CONST`. + // eslint-disable-next-line @typescript-eslint/naming-convention '@src': path.resolve(__dirname, '../../src/'), + // eslint-disable-next-line @typescript-eslint/naming-convention '@userActions': path.resolve(__dirname, '../../src/libs/actions/'), + // eslint-disable-next-line @typescript-eslint/naming-convention '@desktop': path.resolve(__dirname, '../../desktop'), }, @@ -242,6 +257,7 @@ const webpackConfig = ({envFile = '.env', platform = 'web'}) => ({ '.tsx', ], fallback: { + // eslint-disable-next-line @typescript-eslint/naming-convention 'process/browser': require.resolve('process/browser'), crypto: false, }, @@ -275,4 +291,4 @@ const webpackConfig = ({envFile = '.env', platform = 'web'}) => ({ }, }); -module.exports = webpackConfig; +export default getCommonConfiguration; diff --git a/config/webpack/webpack.desktop.js b/config/webpack/webpack.desktop.ts similarity index 56% rename from config/webpack/webpack.desktop.js rename to config/webpack/webpack.desktop.ts index 20ee4a4025df..09314a9c30db 100644 --- a/config/webpack/webpack.desktop.js +++ b/config/webpack/webpack.desktop.ts @@ -1,29 +1,28 @@ -const path = require('path'); -const webpack = require('webpack'); -const _ = require('underscore'); - -const desktopDependencies = require('../../desktop/package.json').dependencies; -const getCommonConfig = require('./webpack.common'); +import path from 'path'; +import type {Configuration} from 'webpack'; +import webpack from 'webpack'; +// eslint-disable-next-line @dword-design/import-alias/prefer-alias, import/no-relative-packages -- alias imports don't work for webpack +import {dependencies as desktopDependencies} from '../../desktop/package.json'; +import type Environment from './types'; +import getCommonConfiguration from './webpack.common'; /** * Desktop creates 2 configurations in parallel * 1. electron-main - the core that serves the app content * 2. web - the app content that would be rendered in electron * Everything is placed in desktop/dist and ready for packaging - * @param {Object} env - * @returns {webpack.Configuration[]} */ -module.exports = (env) => { - const rendererConfig = getCommonConfig({...env, platform: 'desktop'}); +const getConfiguration = (environment: Environment): Configuration[] => { + const rendererConfig = getCommonConfiguration({...environment, platform: 'desktop'}); const outputPath = path.resolve(__dirname, '../../desktop/dist'); rendererConfig.name = 'renderer'; - rendererConfig.output.path = path.join(outputPath, 'www'); + (rendererConfig.output ??= {}).path = path.join(outputPath, 'www'); // Expose react-native-config to desktop-main - const definePlugin = _.find(rendererConfig.plugins, (plugin) => plugin.constructor === webpack.DefinePlugin); + const definePlugin = rendererConfig.plugins?.find((plugin) => plugin?.constructor === webpack.DefinePlugin); - const mainProcessConfig = { + const mainProcessConfig: Configuration = { mode: 'production', name: 'desktop-main', target: 'electron-main', @@ -38,13 +37,15 @@ module.exports = (env) => { }, resolve: rendererConfig.resolve, plugins: [definePlugin], - externals: [..._.keys(desktopDependencies), 'fsevents'], + externals: [...Object.keys(desktopDependencies), 'fsevents'], node: { /** * Disables webpack processing of __dirname and __filename, so it works like in node * https://github.com/webpack/webpack/issues/2010 */ + // eslint-disable-next-line @typescript-eslint/naming-convention __dirname: false, + // eslint-disable-next-line @typescript-eslint/naming-convention __filename: false, }, module: { @@ -60,3 +61,5 @@ module.exports = (env) => { return [mainProcessConfig, rendererConfig]; }; + +export default getConfiguration; diff --git a/config/webpack/webpack.dev.js b/config/webpack/webpack.dev.ts similarity index 67% rename from config/webpack/webpack.dev.js rename to config/webpack/webpack.dev.ts index e28383eff557..8f32a2d95c99 100644 --- a/config/webpack/webpack.dev.js +++ b/config/webpack/webpack.dev.ts @@ -1,34 +1,39 @@ -const path = require('path'); -const portfinder = require('portfinder'); -const {DefinePlugin} = require('webpack'); -const {merge} = require('webpack-merge'); -const {TimeAnalyticsPlugin} = require('time-analytics-webpack-plugin'); -const getCommonConfig = require('./webpack.common'); +import path from 'path'; +import portfinder from 'portfinder'; +import {TimeAnalyticsPlugin} from 'time-analytics-webpack-plugin'; +import type {Configuration} from 'webpack'; +import {DefinePlugin} from 'webpack'; +import type {Configuration as DevServerConfiguration} from 'webpack-dev-server'; +import {merge} from 'webpack-merge'; +import type Environment from './types'; +import getCommonConfiguration from './webpack.common'; const BASE_PORT = 8082; /** * Configuration for the local dev server - * @param {Object} env - * @returns {Configuration} */ -module.exports = (env = {}) => +const getConfiguration = (environment: Environment): Promise => portfinder.getPortPromise({port: BASE_PORT}).then((port) => { // Check if the USE_WEB_PROXY variable has been provided // and rewrite any requests to the local proxy server - const proxySettings = + const proxySettings: Pick = process.env.USE_WEB_PROXY === 'false' ? {} : { proxy: { + // eslint-disable-next-line @typescript-eslint/naming-convention '/api': 'http://[::1]:9000', + // eslint-disable-next-line @typescript-eslint/naming-convention '/staging': 'http://[::1]:9000', + // eslint-disable-next-line @typescript-eslint/naming-convention '/chat-attachments': 'http://[::1]:9000', + // eslint-disable-next-line @typescript-eslint/naming-convention '/receipts': 'http://[::1]:9000', }, }; - const baseConfig = getCommonConfig(env); + const baseConfig = getCommonConfiguration(environment); const config = merge(baseConfig, { mode: 'development', @@ -55,12 +60,13 @@ module.exports = (env = {}) => }, plugins: [ new DefinePlugin({ + // eslint-disable-next-line @typescript-eslint/naming-convention 'process.env.PORT': port, }), ], cache: { type: 'filesystem', - name: env.platform || 'default', + name: environment.platform ?? 'default', buildDependencies: { // By default, webpack and loaders are build dependencies // This (also) makes all dependencies of this config file - build dependencies @@ -78,3 +84,5 @@ module.exports = (env = {}) => return TimeAnalyticsPlugin.wrap(config); }); + +export default getConfiguration; diff --git a/contributingGuides/APPLE_GOOGLE_SIGNIN.md b/contributingGuides/APPLE_GOOGLE_SIGNIN.md index 5c95dfb60950..e6b999b7cb01 100644 --- a/contributingGuides/APPLE_GOOGLE_SIGNIN.md +++ b/contributingGuides/APPLE_GOOGLE_SIGNIN.md @@ -146,7 +146,7 @@ After you've set ngrok up to be able to run on your machine (requires configurin ngrok http 8082 --host-header="dev.new.expensify.com:8082" --subdomain=mysubdomain ``` -The `--host-header` flag is there to avoid webpack errors with header validation. In addition, add `allowedHosts: 'all'` to the dev server config in `webpack.dev.js`: +The `--host-header` flag is there to avoid webpack errors with header validation. In addition, add `allowedHosts: 'all'` to the dev server config in `webpack.dev.ts`: ```js devServer: { @@ -243,9 +243,9 @@ Here's how you can re-enable the SSO buttons in development mode: => { - const devServer = `webpack-dev-server --config config/webpack/webpack.dev.js --port ${port} --env platform=desktop`; - const buildMain = 'webpack watch --config config/webpack/webpack.desktop.js --config-name desktop-main --mode=development'; + .then((port) => { + const devServer = `webpack-dev-server --config config/webpack/webpack.dev.ts --port ${port} --env platform=desktop`; + const buildMain = 'webpack watch --config config/webpack/webpack.desktop.ts --config-name desktop-main --mode=development'; const env = { PORT: port, diff --git a/package-lock.json b/package-lock.json index a347633816ea..a30de7274bed 100644 --- a/package-lock.json +++ b/package-lock.json @@ -182,6 +182,8 @@ "@types/semver": "^7.5.4", "@types/setimmediate": "^1.0.2", "@types/underscore": "^1.11.5", + "@types/webpack": "^5.28.5", + "@types/webpack-bundle-analyzer": "^4.7.0", "@typescript-eslint/eslint-plugin": "^6.13.2", "@typescript-eslint/parser": "^6.13.2", "@vercel/ncc": "0.38.1", @@ -194,9 +196,9 @@ "babel-plugin-react-native-web": "^0.18.7", "babel-plugin-transform-class-properties": "^6.24.1", "babel-plugin-transform-remove-console": "^6.9.4", - "clean-webpack-plugin": "^3.0.0", + "clean-webpack-plugin": "^4.0.0", "concurrently": "^8.2.2", - "copy-webpack-plugin": "^6.4.1", + "copy-webpack-plugin": "^10.1.0", "css-loader": "^6.7.2", "diff-so-fancy": "^1.3.0", "dotenv": "^16.0.3", @@ -6792,6 +6794,61 @@ "version": "2.0.1", "license": "BSD-3-Clause" }, + "node_modules/@mapbox/node-pre-gyp": { + "version": "1.0.10", + "license": "BSD-3-Clause", + "optional": true, + "dependencies": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/make-dir": { + "version": "3.1.0", + "license": "MIT", + "optional": true, + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/make-dir/node_modules/semver": { + "version": "6.3.1", + "license": "ISC", + "optional": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/nopt": { + "version": "5.0.0", + "license": "ISC", + "optional": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/@mapbox/point-geometry": { "version": "0.1.0", "license": "ISC" @@ -11918,6 +11975,19 @@ "dev": true, "license": "MIT" }, + "node_modules/@storybook/builder-webpack4/node_modules/@types/webpack": { + "version": "4.41.38", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/tapable": "^1", + "@types/uglify-js": "*", + "@types/webpack-sources": "*", + "anymatch": "^3.0.0", + "source-map": "^0.6.0" + } + }, "node_modules/@storybook/builder-webpack4/node_modules/@webassemblyjs/helper-buffer": { "version": "1.9.0", "dev": true, @@ -14435,6 +14505,19 @@ "dev": true, "license": "MIT" }, + "node_modules/@storybook/core-server/node_modules/@types/webpack": { + "version": "4.41.38", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/tapable": "^1", + "@types/uglify-js": "*", + "@types/webpack-sources": "*", + "anymatch": "^3.0.0", + "source-map": "^0.6.0" + } + }, "node_modules/@storybook/core-server/node_modules/@webassemblyjs/helper-buffer": { "version": "1.9.0", "dev": true, @@ -15411,6 +15494,19 @@ "dev": true, "license": "MIT" }, + "node_modules/@storybook/manager-webpack4/node_modules/@types/webpack": { + "version": "4.41.38", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/tapable": "^1", + "@types/uglify-js": "*", + "@types/webpack-sources": "*", + "anymatch": "^3.0.0", + "source-map": "^0.6.0" + } + }, "node_modules/@storybook/manager-webpack4/node_modules/@webassemblyjs/helper-buffer": { "version": "1.9.0", "dev": true, @@ -18827,7 +18923,7 @@ } }, "node_modules/@types/source-list-map": { - "version": "0.1.2", + "version": "0.1.6", "dev": true, "license": "MIT" }, @@ -18845,7 +18941,7 @@ "license": "MIT" }, "node_modules/@types/uglify-js": { - "version": "3.17.0", + "version": "3.17.5", "dev": true, "license": "MIT", "dependencies": { @@ -18873,16 +18969,31 @@ "optional": true }, "node_modules/@types/webpack": { - "version": "4.41.32", + "version": "5.28.5", "dev": true, "license": "MIT", "dependencies": { "@types/node": "*", - "@types/tapable": "^1", - "@types/uglify-js": "*", - "@types/webpack-sources": "*", - "anymatch": "^3.0.0", - "source-map": "^0.6.0" + "tapable": "^2.2.0", + "webpack": "^5" + } + }, + "node_modules/@types/webpack-bundle-analyzer": { + "version": "4.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "tapable": "^2.2.0", + "webpack": "^5" + } + }, + "node_modules/@types/webpack-bundle-analyzer/node_modules/tapable": { + "version": "2.2.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" } }, "node_modules/@types/webpack-env": { @@ -18891,7 +19002,7 @@ "license": "MIT" }, "node_modules/@types/webpack-sources": { - "version": "3.2.0", + "version": "3.2.3", "dev": true, "license": "MIT", "dependencies": { @@ -18908,6 +19019,14 @@ "node": ">= 8" } }, + "node_modules/@types/webpack/node_modules/tapable": { + "version": "2.2.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/@types/ws": { "version": "8.5.3", "dev": true, @@ -19884,6 +20003,11 @@ "version": "2.0.6", "license": "BSD-3-Clause" }, + "node_modules/abbrev": { + "version": "1.1.1", + "license": "ISC", + "optional": true + }, "node_modules/abort-controller": { "version": "3.0.0", "license": "MIT", @@ -20397,7 +20521,7 @@ }, "node_modules/aproba": { "version": "1.2.0", - "dev": true, + "devOptional": true, "license": "ISC" }, "node_modules/archiver": { @@ -20463,7 +20587,7 @@ }, "node_modules/are-we-there-yet": { "version": "2.0.0", - "dev": true, + "devOptional": true, "license": "ISC", "dependencies": { "delegates": "^1.0.0", @@ -20475,7 +20599,7 @@ }, "node_modules/are-we-there-yet/node_modules/readable-stream": { "version": "3.6.2", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "inherits": "^2.0.3", @@ -22792,6 +22916,20 @@ ], "license": "CC-BY-4.0" }, + "node_modules/canvas": { + "version": "2.11.2", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@mapbox/node-pre-gyp": "^1.0.0", + "nan": "^2.17.0", + "simple-get": "^3.0.3" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/canvas-size": { "version": "1.2.6", "license": "MIT" @@ -23086,8 +23224,10 @@ }, "node_modules/classnames": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.0.tgz", - "integrity": "sha512-FQuRlyKinxrb5gwJlfVASbSrDlikDJ07426TrfPsdGLvtochowmkbnSFdQGJ2aoXrSetq5KqGV9emvWpy+91xA==" + "license": "MIT", + "workspaces": [ + "benchmarks" + ] }, "node_modules/clean-css": { "version": "5.3.2", @@ -23107,18 +23247,17 @@ } }, "node_modules/clean-webpack-plugin": { - "version": "3.0.0", + "version": "4.0.0", "dev": true, "license": "MIT", "dependencies": { - "@types/webpack": "^4.4.31", "del": "^4.1.1" }, "engines": { - "node": ">=8.9.0" + "node": ">=10.0.0" }, "peerDependencies": { - "webpack": "*" + "webpack": ">=4.0.0 <6.0.0" } }, "node_modules/cli-boxes": { @@ -23330,7 +23469,7 @@ }, "node_modules/color-support": { "version": "1.1.3", - "dev": true, + "devOptional": true, "license": "ISC", "bin": { "color-support": "bin.js" @@ -23791,7 +23930,7 @@ }, "node_modules/console-control-strings": { "version": "1.1.0", - "dev": true, + "devOptional": true, "license": "ISC" }, "node_modules/constants-browserify": { @@ -23892,136 +24031,115 @@ } }, "node_modules/copy-webpack-plugin": { - "version": "6.4.1", + "version": "10.2.4", "dev": true, "license": "MIT", "dependencies": { - "cacache": "^15.0.5", - "fast-glob": "^3.2.4", - "find-cache-dir": "^3.3.1", - "glob-parent": "^5.1.1", - "globby": "^11.0.1", - "loader-utils": "^2.0.0", + "fast-glob": "^3.2.7", + "glob-parent": "^6.0.1", + "globby": "^12.0.2", "normalize-path": "^3.0.0", - "p-limit": "^3.0.2", - "schema-utils": "^3.0.0", - "serialize-javascript": "^5.0.1", - "webpack-sources": "^1.4.3" + "schema-utils": "^4.0.0", + "serialize-javascript": "^6.0.0" }, "engines": { - "node": ">= 10.13.0" + "node": ">= 12.20.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "webpack": "^4.37.0 || ^5.0.0" + "webpack": "^5.1.0" } }, - "node_modules/copy-webpack-plugin/node_modules/find-cache-dir": { - "version": "3.3.2", + "node_modules/copy-webpack-plugin/node_modules/ajv-keywords": { + "version": "5.1.0", "dev": true, "license": "MIT", "dependencies": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - }, - "engines": { - "node": ">=8" + "fast-deep-equal": "^3.1.3" }, - "funding": { - "url": "https://github.com/avajs/find-cache-dir?sponsor=1" + "peerDependencies": { + "ajv": "^8.8.2" } }, - "node_modules/copy-webpack-plugin/node_modules/find-up": { - "version": "4.1.0", + "node_modules/copy-webpack-plugin/node_modules/array-union": { + "version": "3.0.1", "dev": true, "license": "MIT", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/copy-webpack-plugin/node_modules/locate-path": { - "version": "5.0.0", + "node_modules/copy-webpack-plugin/node_modules/glob-parent": { + "version": "6.0.2", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "p-locate": "^4.1.0" + "is-glob": "^4.0.3" }, "engines": { - "node": ">=8" + "node": ">=10.13.0" } }, - "node_modules/copy-webpack-plugin/node_modules/make-dir": { - "version": "3.1.0", + "node_modules/copy-webpack-plugin/node_modules/globby": { + "version": "12.2.0", "dev": true, "license": "MIT", "dependencies": { - "semver": "^6.0.0" + "array-union": "^3.0.1", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.7", + "ignore": "^5.1.9", + "merge2": "^1.4.1", + "slash": "^4.0.0" }, "engines": { - "node": ">=8" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/copy-webpack-plugin/node_modules/p-locate": { - "version": "4.1.0", + "node_modules/copy-webpack-plugin/node_modules/schema-utils": { + "version": "4.2.0", "dev": true, "license": "MIT", "dependencies": { - "p-limit": "^2.2.0" + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" }, "engines": { - "node": ">=8" + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, - "node_modules/copy-webpack-plugin/node_modules/p-locate/node_modules/p-limit": { - "version": "2.3.0", + "node_modules/copy-webpack-plugin/node_modules/serialize-javascript": { + "version": "6.0.2", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "randombytes": "^2.1.0" } }, - "node_modules/copy-webpack-plugin/node_modules/path-exists": { + "node_modules/copy-webpack-plugin/node_modules/slash": { "version": "4.0.0", "dev": true, "license": "MIT", "engines": { - "node": ">=8" - } - }, - "node_modules/copy-webpack-plugin/node_modules/pkg-dir": { - "version": "4.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "find-up": "^4.0.0" + "node": ">=12" }, - "engines": { - "node": ">=8" - } - }, - "node_modules/copy-webpack-plugin/node_modules/semver": { - "version": "6.3.1", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/core-js": { @@ -25151,7 +25269,7 @@ }, "node_modules/delegates": { "version": "1.0.0", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/denodeify": { @@ -25214,6 +25332,14 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/detect-libc": { + "version": "2.0.1", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=8" + } + }, "node_modules/detect-newline": { "version": "3.1.0", "license": "MIT", @@ -27523,14 +27649,16 @@ }, "node_modules/expo-image-loader": { "version": "4.6.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/expo-image-loader/-/expo-image-loader-4.6.0.tgz", + "integrity": "sha512-RHQTDak7/KyhWUxikn2yNzXL7i2cs16cMp6gEAgkHOjVhoCJQoOJ0Ljrt4cKQ3IowxgCuOrAgSUzGkqs7omj8Q==", "peerDependencies": { "expo": "*" } }, "node_modules/expo-image-manipulator": { "version": "11.8.0", - "license": "MIT", + "resolved": "https://registry.npmjs.org/expo-image-manipulator/-/expo-image-manipulator-11.8.0.tgz", + "integrity": "sha512-ZWVrHnYmwJq6h7auk+ropsxcNi+LyZcPFKQc8oy+JA0SaJosfShvkCm7RADWAunHmfPCmjHrhwPGEu/rs7WG/A==", "dependencies": { "expo-image-loader": "~4.6.0" }, @@ -28751,7 +28879,7 @@ }, "node_modules/gauge": { "version": "3.0.2", - "dev": true, + "devOptional": true, "license": "ISC", "dependencies": { "aproba": "^1.0.3 || ^2.0.0", @@ -29225,7 +29353,7 @@ }, "node_modules/has-unicode": { "version": "2.0.1", - "dev": true, + "devOptional": true, "license": "ISC" }, "node_modules/has-value": { @@ -36353,7 +36481,6 @@ }, "node_modules/nan": { "version": "2.17.0", - "dev": true, "license": "MIT", "optional": true }, @@ -36673,7 +36800,7 @@ }, "node_modules/npmlog": { "version": "5.0.1", - "dev": true, + "devOptional": true, "license": "ISC", "dependencies": { "are-we-there-yet": "^2.0.0", @@ -37029,8 +37156,7 @@ }, "node_modules/onfido-sdk-ui": { "version": "14.15.0", - "resolved": "https://registry.npmjs.org/onfido-sdk-ui/-/onfido-sdk-ui-14.15.0.tgz", - "integrity": "sha512-4Z+tnH6pQjK4SyazlzJq17NXO8AnhGcwEACbA3PVbAo90LBpGu1WAZ1r6VidlxFr/oPbu6sg/hisYvfXiqOtTg==" + "license": "SEE LICENSE in LICENSE" }, "node_modules/open": { "version": "8.4.2", @@ -39494,8 +39620,10 @@ }, "node_modules/react-native-release-profiler": { "version": "0.1.6", - "resolved": "https://registry.npmjs.org/react-native-release-profiler/-/react-native-release-profiler-0.1.6.tgz", - "integrity": "sha512-kSAPYjO3PDzV4xbjgj2NoiHtL7EaXmBira/WOcyz6S7mz1MVBoF0Bj74z5jAZo6BoBJRKqmQWI4ep+m0xvoF+g==", + "license": "MIT", + "workspaces": [ + "example" + ], "dependencies": { "@react-native-community/cli": "^12.2.1", "commander": "^11.1.0" @@ -39513,8 +39641,7 @@ }, "node_modules/react-native-release-profiler/node_modules/commander": { "version": "11.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", - "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", + "license": "MIT", "engines": { "node": ">=16" } @@ -39582,8 +39709,7 @@ }, "node_modules/react-native-share": { "version": "10.0.2", - "resolved": "https://registry.npmjs.org/react-native-share/-/react-native-share-10.0.2.tgz", - "integrity": "sha512-EZs4MtsyauAI1zP8xXT1hIFB/pXOZJNDCKcgCpEfTZFXgCUzz8MDVbI1ocP2hA59XHRSkqAQdbJ0BFTpjxOBlg==", + "license": "MIT", "engines": { "node": ">=16" } @@ -41925,6 +42051,57 @@ "version": "3.0.7", "license": "ISC" }, + "node_modules/simple-concat": { + "version": "1.0.1", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "optional": true + }, + "node_modules/simple-get": { + "version": "3.1.1", + "license": "MIT", + "optional": true, + "dependencies": { + "decompress-response": "^4.2.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/simple-get/node_modules/decompress-response": { + "version": "4.2.1", + "license": "MIT", + "optional": true, + "dependencies": { + "mimic-response": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/simple-get/node_modules/mimic-response": { + "version": "2.1.0", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/simple-git": { "version": "3.19.0", "license": "MIT", @@ -46190,7 +46367,7 @@ }, "node_modules/wide-align": { "version": "1.1.5", - "dev": true, + "devOptional": true, "license": "ISC", "dependencies": { "string-width": "^1.0.2 || 2 || 3 || 4" diff --git a/package.json b/package.json index a6171393880c..df2089a8c3a5 100644 --- a/package.json +++ b/package.json @@ -20,10 +20,10 @@ "start": "npx react-native start", "web": "scripts/set-pusher-suffix.sh && concurrently npm:web-proxy npm:web-server", "web-proxy": "ts-node web/proxy.ts", - "web-server": "webpack-dev-server --open --config config/webpack/webpack.dev.js", - "build": "webpack --config config/webpack/webpack.common.js --env envFile=.env.production", - "build-staging": "webpack --config config/webpack/webpack.common.js --env envFile=.env.staging", - "build-adhoc": "webpack --config config/webpack/webpack.common.js --env envFile=.env.adhoc", + "web-server": "webpack-dev-server --open --config config/webpack/webpack.dev.ts", + "build": "webpack --config config/webpack/webpack.common.ts --env file=.env.production", + "build-staging": "webpack --config config/webpack/webpack.common.ts --env file=.env.staging", + "build-adhoc": "webpack --config config/webpack/webpack.common.ts --env file=.env.adhoc", "desktop": "scripts/set-pusher-suffix.sh && ts-node desktop/start.ts", "desktop-build": "scripts/build-desktop.sh production", "desktop-build-staging": "scripts/build-desktop.sh staging", @@ -47,7 +47,7 @@ "storybook-build-staging": "ENV=staging build-storybook -o dist/docs", "gh-actions-build": "./.github/scripts/buildActions.sh", "gh-actions-validate": "./.github/scripts/validateActionsAndWorkflows.sh", - "analyze-packages": "ANALYZE_BUNDLE=true webpack --config config/webpack/webpack.common.js --env envFile=.env.production", + "analyze-packages": "ANALYZE_BUNDLE=true webpack --config config/webpack/webpack.common.ts --env file=.env.production", "symbolicate:android": "npx metro-symbolicate android/app/build/generated/sourcemaps/react/release/index.android.bundle.map", "symbolicate:ios": "npx metro-symbolicate main.jsbundle.map", "symbolicate-release:ios": "scripts/release-profile.ts --platform=ios", @@ -233,6 +233,8 @@ "@types/semver": "^7.5.4", "@types/setimmediate": "^1.0.2", "@types/underscore": "^1.11.5", + "@types/webpack": "^5.28.5", + "@types/webpack-bundle-analyzer": "^4.7.0", "@typescript-eslint/eslint-plugin": "^6.13.2", "@typescript-eslint/parser": "^6.13.2", "@vercel/ncc": "0.38.1", @@ -245,9 +247,9 @@ "babel-plugin-react-native-web": "^0.18.7", "babel-plugin-transform-class-properties": "^6.24.1", "babel-plugin-transform-remove-console": "^6.9.4", - "clean-webpack-plugin": "^3.0.0", + "clean-webpack-plugin": "^4.0.0", + "copy-webpack-plugin": "^10.1.0", "concurrently": "^8.2.2", - "copy-webpack-plugin": "^6.4.1", "css-loader": "^6.7.2", "diff-so-fancy": "^1.3.0", "dotenv": "^16.0.3", diff --git a/scripts/build-desktop.sh b/scripts/build-desktop.sh index efbca35a498c..791f59d73330 100755 --- a/scripts/build-desktop.sh +++ b/scripts/build-desktop.sh @@ -30,7 +30,7 @@ title "Bundling Desktop js Bundle Using Webpack" info " • ELECTRON_ENV: $ELECTRON_ENV" info " • ENV file: $ENV_FILE" info "" -npx webpack --config config/webpack/webpack.desktop.js --env envFile=$ENV_FILE +npx webpack --config config/webpack/webpack.desktop.ts --env file=$ENV_FILE title "Building Desktop App Archive Using Electron" info "" diff --git a/src/types/modules/preload-webpack-plugin.d.ts b/src/types/modules/preload-webpack-plugin.d.ts new file mode 100644 index 000000000000..8f9d33a51080 --- /dev/null +++ b/src/types/modules/preload-webpack-plugin.d.ts @@ -0,0 +1,16 @@ +declare module '@vue/preload-webpack-plugin' { + // eslint-disable-next-line @typescript-eslint/consistent-type-definitions + interface Options { + rel: string; + as: string; + fileWhitelist: RegExp[]; + include: string; + } + + declare class PreloadWebpackPlugin { + constructor(options?: Options); + apply(compiler: Compiler): void; + } + + export default PreloadWebpackPlugin; +}