From fc221eabe296fd4e060f278c24bc746deb6b421f Mon Sep 17 00:00:00 2001 From: Ndricim Rrapi Date: Thu, 14 Dec 2023 13:32:35 +0100 Subject: [PATCH] Update dependencies on CRA-REACT-TEMPLATE (#3582) --- cra-template/package.json | 42 +- cra-template/template.json | 94 +- cra-template/template/config/env.js | 91 - .../template/config/jest/cssTransform.js | 14 - .../template/config/jest/fileTransform.js | 40 - cra-template/template/config/modules.js | 141 - cra-template/template/config/paths.js | 84 - cra-template/template/config/pnpTs.js | 17 - .../template/config/webpack.config.js | 666 - .../config/webpackDevServer.config.js | 103 - cra-template/template/package-lock.json | 12415 ---------------- cra-template/template/public/index.html | 8 + cra-template/template/public/luigi-config.js | 9 +- cra-template/template/public/sampleapp.html | 15 +- cra-template/template/scripts/build.js | 183 - cra-template/template/scripts/server.js | 10 - cra-template/template/scripts/start.js | 128 - cra-template/template/scripts/test.js | 47 - cra-template/template/src/index.css | 9 - cra-template/template/src/index.js | 39 +- cra-template/template/src/views/home.js | 71 +- cra-template/template/src/views/sample1.js | 31 +- cra-template/template/src/views/sample2.js | 31 +- cra-template/template/webpack.config.js | 107 + 24 files changed, 221 insertions(+), 14174 deletions(-) delete mode 100644 cra-template/template/config/env.js delete mode 100644 cra-template/template/config/jest/cssTransform.js delete mode 100644 cra-template/template/config/jest/fileTransform.js delete mode 100644 cra-template/template/config/modules.js delete mode 100644 cra-template/template/config/paths.js delete mode 100644 cra-template/template/config/pnpTs.js delete mode 100644 cra-template/template/config/webpack.config.js delete mode 100644 cra-template/template/config/webpackDevServer.config.js delete mode 100644 cra-template/template/package-lock.json delete mode 100644 cra-template/template/scripts/build.js delete mode 100644 cra-template/template/scripts/server.js delete mode 100644 cra-template/template/scripts/start.js delete mode 100644 cra-template/template/scripts/test.js delete mode 100644 cra-template/template/src/index.css create mode 100644 cra-template/template/webpack.config.js diff --git a/cra-template/package.json b/cra-template/package.json index 66c6eec3c7..e1fff2591b 100644 --- a/cra-template/package.json +++ b/cra-template/package.json @@ -1,44 +1,12 @@ { "name": "@luigi-project/cra-template-luigi-microfrontend", "license": "Apache-2.0", - "version": "1.0.0", - "dependencies": { - "@luigi-project/client": "^1.24.0", - "@luigi-project/core": "^1.24.0", - "@sap-theming/theming-base-content": "^11.1.41", - "@testing-library/jest-dom": "^5.16.5", - "@testing-library/react": "^13.3.0", - "@testing-library/user-event": "^13.5.0", - "fundamental-styles": "^0.24.4", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "react-scripts": "5.0.1", - "web-vitals": "^2.1.4" - }, + "version": "1.0.1", + "keywords": ["cra-template-luigi", "microfrontend", "luigi", "luigi-microfrontend"], "scripts": { - "start": "node scripts/start.js", - "build": "node scripts/build.js", - "test": "node scripts/test.js", - "serve": "node scripts/server.js build" }, - "eslintConfig": { - "extends": [ - "react-app" - ] - }, - "browserslist": { - "production": [ - ">0.2%", - "not dead", - "not op_mini all" - ], - "development": [ - "last 1 chrome version", - "last 1 firefox version", - "last 1 safari version" - ] + "dependencies": { }, - "engines": { - "node": ">=18" + "devDependencies": { } -} \ No newline at end of file +} diff --git a/cra-template/template.json b/cra-template/template.json index 701b03630e..90b05bbd51 100644 --- a/cra-template/template.json +++ b/cra-template/template.json @@ -1,86 +1,28 @@ { "package": { "dependencies": { - "@testing-library/jest-dom": "^5.14.1", - "@testing-library/react": "^13.0.0", - "@testing-library/user-event": "^13.2.1", - "web-vitals": "^2.1.0", - "@luigi-project/client": "^1.24.0", - "@luigi-project/core": "^1.24.0", - "@sap-theming/theming-base-content": "^11.1.41", - "fundamental-styles": "^0.24.4", - "@svgr/webpack": "4.3.2", - "@typescript-eslint/eslint-plugin": "^2.2.0", - "@typescript-eslint/parser": "^2.2.0", - "@babel/core": "^7.17.4", - "babel-eslint": "^10.1.0", - "babel-jest": "^27.5.1", - "babel-loader": "^8.2.3", - "babel-plugin-named-asset-import": "^0.3.8", - "babel-preset-react-app": "^10.0.1", - "camelcase": "^5.2.0", - "case-sensitive-paths-webpack-plugin": "2.2.0", - "css-loader": "2.1.1", - "dotenv": "6.2.0", - "dotenv-expand": "5.1.0", - "eslint": "^6.1.0", - "eslint-config-react-app": "^7.0.1", - "eslint-loader": "3.0.2", - "eslint-plugin-flowtype": "3.13.0", - "eslint-plugin-import": "2.18.2", - "eslint-plugin-jsx-a11y": "6.2.3", - "eslint-plugin-react": "7.14.3", - "eslint-plugin-react-hooks": "^1.6.1", - "file-loader": "3.0.1", - "fs-extra": "7.0.1", - "html-webpack-plugin": "4.0.0-beta.5", - "identity-obj-proxy": "3.0.0", - "is-wsl": "^1.1.0", - "jest": "^27.5.1", - "jest-environment-jsdom-fourteen": "^1.0.1", - "jest-resolve": "^27.5.1", - "jest-watch-typeahead": "0.4.0", - "mini-css-extract-plugin": "0.8.0", - "optimize-css-assets-webpack-plugin": "5.0.3", - "pnp-webpack-plugin": "1.5.0", - "postcss-flexbugs-fixes": "4.1.0", - "postcss-loader": "3.0.0", - "postcss-normalize": "7.0.1", - "postcss-preset-env": "6.7.0", - "postcss-safe-parser": "4.0.1", - "react-app-polyfill": "^1.0.4", - "react-dev-utils": "^9.1.0", - "react-router-dom": "^5.1.2", - "resolve": "1.12.0", - "resolve-url-loader": "3.1.0", - "sass-loader": "7.2.0", - "semver": "6.3.0", - "style-loader": "1.0.0", - "terser-webpack-plugin": "1.4.1", - "ts-pnp": "1.1.4", - "url-loader": "2.1.0", - "webpack": "4.41.0", - "webpack-dev-server": "3.2.1", - "webpack-manifest-plugin": "2.1.1", - "workbox-webpack-plugin": "4.3.1", - "ajv": "8.11.0" + "@luigi-project/client": "^1.25.1", + "@luigi-project/core": "^1.25.1", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-router-dom": "^6.4.3" }, "devDependencies": { - "copy-webpack-plugin": "~4.4.1" - }, - "eslintConfig": { - "extends": ["react-app", "react-app/jest"] + "@babel/core": "^7.20.2", + "@babel/preset-env": "^7.20.2", + "@babel/preset-react": "^7.18.6", + "babel-loader": "^9.1.0", + "copy-webpack-plugin": "^11.0.0", + "html-webpack-plugin": "^5.5.0", + "webpack": "^5.75.0", + "webpack-cli": "^5.0.0", + "webpack-dev-server": "^4.11.0" }, "scripts": { - "start": "node scripts/start.js", - "build": "node scripts/build.js", - "test": "node scripts/test.js", - "serve": "node scripts/server.js build" - }, - "babel": { - "presets": [ - "react-app" - ] + "test": "echo \"Error: no test specified\" && exit 1", + "start": "webpack-dev-server --mode development", + "build": "webpack --mode production", + "serve": "webpack-dev-server --mode production" } } } \ No newline at end of file diff --git a/cra-template/template/config/env.js b/cra-template/template/config/env.js deleted file mode 100644 index f98564f17a..0000000000 --- a/cra-template/template/config/env.js +++ /dev/null @@ -1,91 +0,0 @@ -'use strict'; - -const fs = require('fs'); -const path = require('path'); -const paths = require('./paths'); - -// Make sure that including paths.js after env.js will read .env variables. -delete require.cache[require.resolve('./paths')]; - -const NODE_ENV = process.env.NODE_ENV; -if (!NODE_ENV) { - throw new Error('The NODE_ENV environment variable is required but was not specified.'); -} - -// https://github.com/bkeepers/dotenv#what-other-env-files-can-i-use -const dotenvFiles = [ - `${paths.dotenv}.${NODE_ENV}.local`, - `${paths.dotenv}.${NODE_ENV}`, - // Don't include `.env.local` for `test` environment - // since normally you expect tests to produce the same - // results for everyone - NODE_ENV !== 'test' && `${paths.dotenv}.local`, - paths.dotenv -].filter(Boolean); - -// Load environment variables from .env* files. Suppress warnings using silent -// if this file is missing. dotenv will never modify any environment variables -// that have already been set. Variable expansion is supported in .env files. -// https://github.com/motdotla/dotenv -// https://github.com/motdotla/dotenv-expand -dotenvFiles.forEach(dotenvFile => { - if (fs.existsSync(dotenvFile)) { - require('dotenv-expand')( - require('dotenv').config({ - path: dotenvFile - }) - ); - } -}); - -// We support resolving modules according to `NODE_PATH`. -// This lets you use absolute paths in imports inside large monorepos: -// https://github.com/facebook/create-react-app/issues/253. -// It works similar to `NODE_PATH` in Node itself: -// https://nodejs.org/api/modules.html#modules_loading_from_the_global_folders -// Note that unlike in Node, only *relative* paths from `NODE_PATH` are honored. -// Otherwise, we risk importing Node.js core modules into an app instead of Webpack shims. -// https://github.com/facebook/create-react-app/issues/1023#issuecomment-265344421 -// We also resolve them to make sure all tools using them work consistently. -const appDirectory = fs.realpathSync(process.cwd()); -process.env.NODE_PATH = (process.env.NODE_PATH || '') - .split(path.delimiter) - .filter(folder => folder && !path.isAbsolute(folder)) - .map(folder => path.resolve(appDirectory, folder)) - .join(path.delimiter); - -// Grab NODE_ENV and REACT_APP_* environment variables and prepare them to be -// injected into the application via DefinePlugin in Webpack configuration. -const REACT_APP = /^REACT_APP_/i; - -function getClientEnvironment(publicUrl) { - const raw = Object.keys(process.env) - .filter(key => REACT_APP.test(key)) - .reduce( - (env, key) => { - env[key] = process.env[key]; - return env; - }, - { - // Useful for determining whether we’re running in production mode. - // Most importantly, it switches React into the correct mode. - NODE_ENV: process.env.NODE_ENV || 'development', - // Useful for resolving the correct path to static assets in `public`. - // For example, . - // This should only be used as an escape hatch. Normally you would put - // images into the `src` and `import` them in code to get their paths. - PUBLIC_URL: publicUrl - } - ); - // Stringify all values so we can feed into Webpack DefinePlugin - const stringified = { - 'process.env': Object.keys(raw).reduce((env, key) => { - env[key] = JSON.stringify(raw[key]); - return env; - }, {}) - }; - - return { raw, stringified }; -} - -module.exports = getClientEnvironment; diff --git a/cra-template/template/config/jest/cssTransform.js b/cra-template/template/config/jest/cssTransform.js deleted file mode 100644 index 3d75506588..0000000000 --- a/cra-template/template/config/jest/cssTransform.js +++ /dev/null @@ -1,14 +0,0 @@ -'use strict'; - -// This is a custom Jest transformer turning style imports into empty objects. -// http://facebook.github.io/jest/docs/en/webpack.html - -module.exports = { - process() { - return 'module.exports = {};'; - }, - getCacheKey() { - // The output is always the same. - return 'cssTransform'; - } -}; diff --git a/cra-template/template/config/jest/fileTransform.js b/cra-template/template/config/jest/fileTransform.js deleted file mode 100644 index 274803ff79..0000000000 --- a/cra-template/template/config/jest/fileTransform.js +++ /dev/null @@ -1,40 +0,0 @@ -'use strict'; - -const path = require('path'); -const camelcase = require('camelcase'); - -// This is a custom Jest transformer turning file imports into filenames. -// http://facebook.github.io/jest/docs/en/webpack.html - -module.exports = { - process(src, filename) { - const assetFilename = JSON.stringify(path.basename(filename)); - - if (filename.match(/\.svg$/)) { - // Based on how SVGR generates a component name: - // https://github.com/smooth-code/svgr/blob/01b194cf967347d43d4cbe6b434404731b87cf27/packages/core/src/state.js#L6 - const pascalCaseFilename = camelcase(path.parse(filename).name, { - pascalCase: true - }); - const componentName = `Svg${pascalCaseFilename}`; - return `const React = require('react'); - module.exports = { - __esModule: true, - default: ${assetFilename}, - ReactComponent: React.forwardRef(function ${componentName}(props, ref) { - return { - $$typeof: Symbol.for('react.element'), - type: 'svg', - ref: ref, - key: null, - props: Object.assign({}, props, { - children: ${assetFilename} - }) - }; - }), - };`; - } - - return `module.exports = ${assetFilename};`; - } -}; diff --git a/cra-template/template/config/modules.js b/cra-template/template/config/modules.js deleted file mode 100644 index 442bc51ca0..0000000000 --- a/cra-template/template/config/modules.js +++ /dev/null @@ -1,141 +0,0 @@ -'use strict'; - -const fs = require('fs'); -const path = require('path'); -const paths = require('./paths'); -const chalk = require('react-dev-utils/chalk'); -const resolve = require('resolve'); - -/** - * Get additional module paths based on the baseUrl of a compilerOptions object. - * - * @param {Object} options - */ -function getAdditionalModulePaths(options = {}) { - const baseUrl = options.baseUrl; - - // We need to explicitly check for null and undefined (and not a falsy value) because - // TypeScript treats an empty string as `.`. - if (baseUrl == null) { - // If there's no baseUrl set we respect NODE_PATH - // Note that NODE_PATH is deprecated and will be removed - // in the next major release of create-react-app. - - const nodePath = process.env.NODE_PATH || ''; - return nodePath.split(path.delimiter).filter(Boolean); - } - - const baseUrlResolved = path.resolve(paths.appPath, baseUrl); - - // We don't need to do anything if `baseUrl` is set to `node_modules`. This is - // the default behavior. - if (path.relative(paths.appNodeModules, baseUrlResolved) === '') { - return null; - } - - // Allow the user set the `baseUrl` to `appSrc`. - if (path.relative(paths.appSrc, baseUrlResolved) === '') { - return [paths.appSrc]; - } - - // If the path is equal to the root directory we ignore it here. - // We don't want to allow importing from the root directly as source files are - // not transpiled outside of `src`. We do allow importing them with the - // absolute path (e.g. `src/Components/Button.js`) but we set that up with - // an alias. - if (path.relative(paths.appPath, baseUrlResolved) === '') { - return null; - } - - // Otherwise, throw an error. - throw new Error( - chalk.red.bold( - "Your project's `baseUrl` can only be set to `src` or `node_modules`." + - ' Create React App does not support other values at this time.' - ) - ); -} - -/** - * Get webpack aliases based on the baseUrl of a compilerOptions object. - * - * @param {*} options - */ -function getWebpackAliases(options = {}) { - const baseUrl = options.baseUrl; - - if (!baseUrl) { - return {}; - } - - const baseUrlResolved = path.resolve(paths.appPath, baseUrl); - - if (path.relative(paths.appPath, baseUrlResolved) === '') { - return { - src: paths.appSrc - }; - } -} - -/** - * Get jest aliases based on the baseUrl of a compilerOptions object. - * - * @param {*} options - */ -function getJestAliases(options = {}) { - const baseUrl = options.baseUrl; - - if (!baseUrl) { - return {}; - } - - const baseUrlResolved = path.resolve(paths.appPath, baseUrl); - - if (path.relative(paths.appPath, baseUrlResolved) === '') { - return { - 'src/(.*)$': '/src/$1' - }; - } -} - -function getModules() { - // Check if TypeScript is setup - const hasTsConfig = fs.existsSync(paths.appTsConfig); - const hasJsConfig = fs.existsSync(paths.appJsConfig); - - if (hasTsConfig && hasJsConfig) { - throw new Error( - 'You have both a tsconfig.json and a jsconfig.json. If you are using TypeScript please remove your jsconfig.json file.' - ); - } - - let config; - - // If there's a tsconfig.json we assume it's a - // TypeScript project and set up the config - // based on tsconfig.json - if (hasTsConfig) { - const ts = require(resolve.sync('typescript', { - basedir: paths.appNodeModules - })); - config = ts.readConfigFile(paths.appTsConfig, ts.sys.readFile).config; - // Otherwise we'll check if there is jsconfig.json - // for non TS projects. - } else if (hasJsConfig) { - config = require(paths.appJsConfig); - } - - config = config || {}; - const options = config.compilerOptions || {}; - - const additionalModulePaths = getAdditionalModulePaths(options); - - return { - additionalModulePaths: additionalModulePaths, - webpackAliases: getWebpackAliases(options), - jestAliases: getJestAliases(options), - hasTsConfig - }; -} - -module.exports = getModules(); diff --git a/cra-template/template/config/paths.js b/cra-template/template/config/paths.js deleted file mode 100644 index 3a0febc1d1..0000000000 --- a/cra-template/template/config/paths.js +++ /dev/null @@ -1,84 +0,0 @@ -'use strict'; - -const path = require('path'); -const fs = require('fs'); -const url = require('url'); - -// Make sure any symlinks in the project folder are resolved: -// https://github.com/facebook/create-react-app/issues/637 -const appDirectory = fs.realpathSync(process.cwd()); -const resolveApp = relativePath => path.resolve(appDirectory, relativePath); - -const envPublicUrl = process.env.PUBLIC_URL; - -function ensureSlash(inputPath, needsSlash) { - const hasSlash = inputPath.endsWith('/'); - if (hasSlash && !needsSlash) { - return inputPath.substr(0, inputPath.length - 1); - } else if (!hasSlash && needsSlash) { - return `${inputPath}/`; - } else { - return inputPath; - } -} - -const getPublicUrl = appPackageJson => envPublicUrl || require(appPackageJson).homepage; - -// We use `PUBLIC_URL` environment variable or "homepage" field to infer -// "public path" at which the app is served. -// Webpack needs to know it to put the right + diff --git a/cra-template/template/public/luigi-config.js b/cra-template/template/public/luigi-config.js index 9c48294032..1e9419c4b6 100644 --- a/cra-template/template/public/luigi-config.js +++ b/cra-template/template/public/luigi-config.js @@ -5,19 +5,22 @@ Luigi.setConfig({ pathSegment: 'home', label: 'Home', icon: 'home', - viewUrl: '/sampleapp.html#/home', + viewUrl: '/sampleapp.html/#/microfrontend/home', + loadingIndicator: { + enabled: false + }, children: [ { pathSegment: 'sample1', label: 'First', icon: 'nutrition-activity', - viewUrl: '/sampleapp.html#/sample1' + viewUrl: '/sampleapp.html/#/microfrontend/sample1' }, { pathSegment: 'sample2', label: 'Second', icon: 'paper-plane', - viewUrl: '/sampleapp.html#/sample2' + viewUrl: '/sampleapp.html/#/microfrontend/sample2' }, { category: { label: 'Links', icon: 'cloud' }, diff --git a/cra-template/template/public/sampleapp.html b/cra-template/template/public/sampleapp.html index 7bf9fc235a..91f77755d4 100644 --- a/cra-template/template/public/sampleapp.html +++ b/cra-template/template/public/sampleapp.html @@ -1,17 +1,16 @@ - - - - - React App + + + + Luigi Simple React App + + +
diff --git a/cra-template/template/scripts/build.js b/cra-template/template/scripts/build.js deleted file mode 100644 index 9325cbf0ce..0000000000 --- a/cra-template/template/scripts/build.js +++ /dev/null @@ -1,183 +0,0 @@ -'use strict'; - -// Do this as the first thing so that any code reading it knows the right env. -process.env.BABEL_ENV = 'production'; -process.env.NODE_ENV = 'production'; - -// Makes the script crash on unhandled rejections instead of silently -// ignoring them. In the future, promise rejections that are not handled will -// terminate the Node.js process with a non-zero exit code. -process.on('unhandledRejection', err => { - throw err; -}); - -// Ensure environment variables are read. -require('../config/env'); - -const path = require('path'); -const chalk = require('react-dev-utils/chalk'); -const fs = require('fs-extra'); -const webpack = require('webpack'); -const configFactory = require('../config/webpack.config'); -const paths = require('../config/paths'); -const checkRequiredFiles = require('react-dev-utils/checkRequiredFiles'); -const formatWebpackMessages = require('react-dev-utils/formatWebpackMessages'); -const printHostingInstructions = require('react-dev-utils/printHostingInstructions'); -const FileSizeReporter = require('react-dev-utils/FileSizeReporter'); -const printBuildError = require('react-dev-utils/printBuildError'); - -const measureFileSizesBeforeBuild = FileSizeReporter.measureFileSizesBeforeBuild; -const printFileSizesAfterBuild = FileSizeReporter.printFileSizesAfterBuild; -const useYarn = fs.existsSync(paths.yarnLockFile); - -// These sizes are pretty large. We'll warn for bundles exceeding them. -const WARN_AFTER_BUNDLE_GZIP_SIZE = 512 * 1024; -const WARN_AFTER_CHUNK_GZIP_SIZE = 1024 * 1024; - -const isInteractive = process.stdout.isTTY; - -// Warn and crash if required files are missing -if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) { - process.exit(1); -} - -// Generate configuration -const config = configFactory('production'); - -// We require that you explicitly set browsers and do not fall back to -// browserslist defaults. -const { checkBrowsers } = require('react-dev-utils/browsersHelper'); -checkBrowsers(paths.appPath, isInteractive) - .then(() => { - // First, read the current file sizes in build directory. - // This lets us display how much they changed later. - return measureFileSizesBeforeBuild(paths.appBuild); - }) - .then(previousFileSizes => { - // Remove all content but keep the directory so that - // if you're in it, you don't end up in Trash - fs.emptyDirSync(paths.appBuild); - // Merge with the public folder - copyPublicFolder(); - // Start the webpack build - return build(previousFileSizes); - }) - .then( - ({ stats, previousFileSizes, warnings }) => { - if (warnings.length) { - console.log(chalk.yellow('Compiled with warnings.\n')); - console.log(warnings.join('\n\n')); - console.log( - '\nSearch for the ' + chalk.underline(chalk.yellow('keywords')) + ' to learn more about each warning.' - ); - console.log('To ignore, add ' + chalk.cyan('// eslint-disable-next-line') + ' to the line before.\n'); - } else { - console.log(chalk.green('Compiled successfully.\n')); - } - - console.log('File sizes after gzip:\n'); - printFileSizesAfterBuild( - stats, - previousFileSizes, - paths.appBuild, - WARN_AFTER_BUNDLE_GZIP_SIZE, - WARN_AFTER_CHUNK_GZIP_SIZE - ); - console.log(); - - const appPackage = require(paths.appPackageJson); - const publicUrl = paths.publicUrl; - const publicPath = config.output.publicPath; - const buildFolder = path.relative(process.cwd(), paths.appBuild); - printHostingInstructions(appPackage, publicUrl, publicPath, buildFolder, useYarn); - }, - err => { - const tscCompileOnError = process.env.TSC_COMPILE_ON_ERROR === 'true'; - if (tscCompileOnError) { - console.log( - chalk.yellow( - 'Compiled with the following type errors (you may want to check these before deploying your app):\n' - ) - ); - printBuildError(err); - } else { - console.log(chalk.red('Failed to compile.\n')); - printBuildError(err); - process.exit(1); - } - } - ) - .catch(err => { - if (err && err.message) { - console.log(err.message); - } - process.exit(1); - }); - -// Create the production build and print the deployment instructions. -function build(previousFileSizes) { - // We used to support resolving modules according to `NODE_PATH`. - // This now has been deprecated in favor of jsconfig/tsconfig.json - // This lets you use absolute paths in imports inside large monorepos: - if (process.env.NODE_PATH) { - console.log( - chalk.yellow( - 'Setting NODE_PATH to resolve modules absolutely has been deprecated in favor of setting baseUrl in jsconfig.json (or tsconfig.json if you are using TypeScript) and will be removed in a future major release of create-react-app.' - ) - ); - console.log(); - } - - console.log('Creating an optimized production build...'); - - const compiler = webpack(config); - return new Promise((resolve, reject) => { - compiler.run((err, stats) => { - let messages; - if (err) { - if (!err.message) { - return reject(err); - } - messages = formatWebpackMessages({ - errors: [err.message], - warnings: [] - }); - } else { - messages = formatWebpackMessages(stats.toJson({ all: false, warnings: true, errors: true })); - } - if (messages.errors.length) { - // Only keep the first error. Others are often indicative - // of the same problem, but confuse the reader with noise. - if (messages.errors.length > 1) { - messages.errors.length = 1; - } - return reject(new Error(messages.errors.join('\n\n'))); - } - if ( - process.env.CI && - (typeof process.env.CI !== 'string' || process.env.CI.toLowerCase() !== 'false') && - messages.warnings.length - ) { - console.log( - chalk.yellow( - '\nTreating warnings as errors because process.env.CI = true.\n' + 'Most CI servers set it automatically.\n' - ) - ); - return reject(new Error(messages.warnings.join('\n\n'))); - } - - return resolve({ - stats, - previousFileSizes, - warnings: messages.warnings - }); - }); - }); -} - -function copyPublicFolder() { - fs.copySync(paths.appPublic, paths.appBuild, { - dereference: true, - filter: file => file !== paths.appHtml - }); -} diff --git a/cra-template/template/scripts/server.js b/cra-template/template/scripts/server.js deleted file mode 100644 index 2486813e87..0000000000 --- a/cra-template/template/scripts/server.js +++ /dev/null @@ -1,10 +0,0 @@ -const express = require('express'); -const path = require('path'); -const app = express(); -var buildFolder = process.argv[2]; -app.use(express.static(path.join(__dirname, '../', buildFolder))); -app.get('/*', function(req, res) { - res.sendFile(path.join(__dirname, '../', buildFolder, 'index.html')); -}); -console.log('Serving on port: 9000'); -app.listen(9000); diff --git a/cra-template/template/scripts/start.js b/cra-template/template/scripts/start.js deleted file mode 100644 index 564afce02f..0000000000 --- a/cra-template/template/scripts/start.js +++ /dev/null @@ -1,128 +0,0 @@ -'use strict'; - -// Do this as the first thing so that any code reading it knows the right env. -process.env.BABEL_ENV = 'development'; -process.env.NODE_ENV = 'development'; - -// Makes the script crash on unhandled rejections instead of silently -// ignoring them. In the future, promise rejections that are not handled will -// terminate the Node.js process with a non-zero exit code. -process.on('unhandledRejection', err => { - throw err; -}); - -// Ensure environment variables are read. -require('../config/env'); - -const fs = require('fs'); -const chalk = require('react-dev-utils/chalk'); -const webpack = require('webpack'); -const WebpackDevServer = require('webpack-dev-server'); -const clearConsole = require('react-dev-utils/clearConsole'); -const checkRequiredFiles = require('react-dev-utils/checkRequiredFiles'); -const { choosePort, createCompiler, prepareProxy, prepareUrls } = require('react-dev-utils/WebpackDevServerUtils'); -const openBrowser = require('react-dev-utils/openBrowser'); -const paths = require('../config/paths'); -const configFactory = require('../config/webpack.config'); -const createDevServerConfig = require('../config/webpackDevServer.config'); - -const useYarn = fs.existsSync(paths.yarnLockFile); -const isInteractive = process.stdout.isTTY; - -// Warn and crash if required files are missing -if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) { - process.exit(1); -} - -// Tools like Cloud9 rely on this. -const DEFAULT_PORT = parseInt(process.env.PORT, 10) || 3000; -const HOST = process.env.HOST || '0.0.0.0'; - -if (process.env.HOST) { - console.log( - chalk.cyan(`Attempting to bind to HOST environment variable: ${chalk.yellow(chalk.bold(process.env.HOST))}`) - ); - console.log(`If this was unintentional, check that you haven't mistakenly set it in your shell.`); - console.log(`Learn more here: ${chalk.yellow('https://bit.ly/CRA-advanced-config')}`); - console.log(); -} - -// We require that you explicitly set browsers and do not fall back to -// browserslist defaults. -const { checkBrowsers } = require('react-dev-utils/browsersHelper'); -checkBrowsers(paths.appPath, isInteractive) - .then(() => { - // We attempt to use the default port but if it is busy, we offer the user to - // run on a different port. `choosePort()` Promise resolves to the next free port. - return choosePort(HOST, DEFAULT_PORT); - }) - .then(port => { - if (port == null) { - // We have not found a port. - return; - } - const config = configFactory('development'); - const protocol = process.env.HTTPS === 'true' ? 'https' : 'http'; - const appName = require(paths.appPackageJson).name; - const useTypeScript = fs.existsSync(paths.appTsConfig); - const tscCompileOnError = process.env.TSC_COMPILE_ON_ERROR === 'true'; - const urls = prepareUrls(protocol, HOST, port); - const devSocket = { - warnings: warnings => devServer.sockWrite(devServer.sockets, 'warnings', warnings), - errors: errors => devServer.sockWrite(devServer.sockets, 'errors', errors) - }; - // Create a webpack compiler that is configured with custom messages. - const compiler = createCompiler({ - appName, - config, - devSocket, - urls, - useYarn, - useTypeScript, - tscCompileOnError, - webpack - }); - // Load proxy config - const proxySetting = require(paths.appPackageJson).proxy; - const proxyConfig = prepareProxy(proxySetting, paths.appPublic); - // Serve webpack assets generated by the compiler over a web server. - const serverConfig = createDevServerConfig(proxyConfig, urls.lanUrlForConfig); - const devServer = new WebpackDevServer(compiler, serverConfig); - // Launch WebpackDevServer. - devServer.listen(port, HOST, err => { - if (err) { - return console.log(err); - } - if (isInteractive) { - clearConsole(); - } - - // We used to support resolving modules according to `NODE_PATH`. - // This now has been deprecated in favor of jsconfig/tsconfig.json - // This lets you use absolute paths in imports inside large monorepos: - if (process.env.NODE_PATH) { - console.log( - chalk.yellow( - 'Setting NODE_PATH to resolve modules absolutely has been deprecated in favor of setting baseUrl in jsconfig.json (or tsconfig.json if you are using TypeScript) and will be removed in a future major release of create-react-app.' - ) - ); - console.log(); - } - - console.log(chalk.cyan('Starting the development server...\n')); - openBrowser(urls.localUrlForBrowser); - }); - - ['SIGINT', 'SIGTERM'].forEach(function(sig) { - process.on(sig, function() { - devServer.close(); - process.exit(); - }); - }); - }) - .catch(err => { - if (err && err.message) { - console.log(err.message); - } - process.exit(1); - }); diff --git a/cra-template/template/scripts/test.js b/cra-template/template/scripts/test.js deleted file mode 100644 index a1896130a6..0000000000 --- a/cra-template/template/scripts/test.js +++ /dev/null @@ -1,47 +0,0 @@ -'use strict'; - -// Do this as the first thing so that any code reading it knows the right env. -process.env.BABEL_ENV = 'test'; -process.env.NODE_ENV = 'test'; -process.env.PUBLIC_URL = ''; - -// Makes the script crash on unhandled rejections instead of silently -// ignoring them. In the future, promise rejections that are not handled will -// terminate the Node.js process with a non-zero exit code. -process.on('unhandledRejection', err => { - throw err; -}); - -// Ensure environment variables are read. -require('../config/env'); - -const jest = require('jest'); -const execSync = require('child_process').execSync; -let argv = process.argv.slice(2); - -function isInGitRepository() { - try { - execSync('git rev-parse --is-inside-work-tree', { stdio: 'ignore' }); - return true; - } catch (e) { - return false; - } -} - -function isInMercurialRepository() { - try { - execSync('hg --cwd . root', { stdio: 'ignore' }); - return true; - } catch (e) { - return false; - } -} - -// Watch unless on CI or explicitly running all tests -if (!process.env.CI && argv.indexOf('--watchAll') === -1 && argv.indexOf('--watchAll=false') === -1) { - // https://github.com/facebook/create-react-app/issues/5210 - const hasSourceControl = isInGitRepository() || isInMercurialRepository(); - argv.push(hasSourceControl ? '--watch' : '--watchAll'); -} - -jest.run(argv); diff --git a/cra-template/template/src/index.css b/cra-template/template/src/index.css deleted file mode 100644 index cbe8ee15af..0000000000 --- a/cra-template/template/src/index.css +++ /dev/null @@ -1,9 +0,0 @@ -body { - padding: 0; - margin: 0; - position: absolute; -} - -.fd-panel { - padding: 15px; -} diff --git a/cra-template/template/src/index.js b/cra-template/template/src/index.js index 88af3f11d5..0704b7836e 100644 --- a/cra-template/template/src/index.js +++ b/cra-template/template/src/index.js @@ -1,30 +1,21 @@ -import React, { Component } from 'react'; -import { createRoot } from 'react-dom/client.js'; -import { BrowserRouter, Route } from 'react-router-dom'; +import React from 'react'; +import { createRoot } from 'react-dom/client'; +import { HashRouter as Router, Routes, Route } from 'react-router-dom'; import Home from './views/home.js'; import Sample1 from './views/sample1.js'; import Sample2 from './views/sample2.js'; -import { addInitListener } from '@luigi-project/client'; -import './index.css'; - -class App extends Component { - constructor(props) { - super(props); - addInitListener(() => { - console.log('Luigi Client initialized.'); - }); - } - render() { - return ( - - - - - - ); - } -} const container = document.getElementById('root'); const root = createRoot(container); -root.render(); + +root.render( + + + + } /> + } /> + } /> + + + +); diff --git a/cra-template/template/src/views/home.js b/cra-template/template/src/views/home.js index 97a427e046..66ae8317fc 100644 --- a/cra-template/template/src/views/home.js +++ b/cra-template/template/src/views/home.js @@ -1,5 +1,4 @@ -import React, { Component } from 'react'; -import 'fundamental-styles'; +import React, { Component, useState, useEffect } from 'react'; import { addInitListener, addContextUpdateListener, @@ -7,44 +6,36 @@ import { removeInitListener } from '@luigi-project/client'; -export default class Home extends Component { - constructor(props) { - super(props); - this.state = { - message: '' - }; - this.initListener = null; - this.contextUpdateListener = null; - } - - componentDidMount() { - this.initListener = addInitListener(initialContext => { - this.setState({ - message: 'Luigi Client initialized.' - }); - }); - this.contextUpdateListener = addContextUpdateListener(updatedContext => { - this.setState({ - message: 'Luigi Client updated.' - }); - }); - } +const Home = () => { + const [message, setMessage] = useState(''); + const [initListener, setInitListener] = useState(null); + const [contextUpdateListener, setContextUpdateListener] = useState(null); - componentWillUnmount() { - removeContextUpdateListener(this.contextUpdateListener); - removeInitListener(this.initListener); - } + useEffect(() => { + setInitListener( + addInitListener(initialContext => { + setMessage('Luigi Client initialized.'); + }) + ); - render() { - return ( -
-
-
-

Home

-
-
{this.state.message}
-
-
+ setContextUpdateListener( + addContextUpdateListener(updatedContext => { + setMessage('Luigi Client updated.'); + }) ); - } -} + + return function cleanup() { + removeContextUpdateListener(contextUpdateListener); + removeInitListener(initListener); + }; + }, []); + + return ( +
+

Home

+
{message}
+
+ ); +}; + +export default Home; diff --git a/cra-template/template/src/views/sample1.js b/cra-template/template/src/views/sample1.js index 7e34724fb7..3d8372dfd7 100644 --- a/cra-template/template/src/views/sample1.js +++ b/cra-template/template/src/views/sample1.js @@ -1,20 +1,13 @@ -import React, { Component } from 'react'; -import 'fundamental-styles'; +import React from 'react'; -export default class Sample1 extends Component { - render() { - return ( -
-
-
-

Sample 1

-
-
- Luigi ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et - dolore magna aliquyam erat, sed diam voluptua. -
-
-
- ); - } -} +const Sample1 = () => { + return ( +
+

Sample 1

+ Luigi ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et + dolore magna aliquyam erat, sed diam voluptua. +
+ ); +}; + +export default Sample1; diff --git a/cra-template/template/src/views/sample2.js b/cra-template/template/src/views/sample2.js index 8cedce1d80..dc9a9c69cb 100644 --- a/cra-template/template/src/views/sample2.js +++ b/cra-template/template/src/views/sample2.js @@ -1,20 +1,13 @@ -import React, { Component } from 'react'; -import 'fundamental-styles'; +import React from 'react'; -export default class Sample1 extends Component { - render() { - return ( -
-
-
-

Sample 2

-
-
- Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea - commodo consequat. -
-
-
- ); - } -} +const Sample2 = () => { + return ( +
+

Sample 2

+ Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea + commodo consequat. +
+ ); +}; + +export default Sample2; diff --git a/cra-template/template/webpack.config.js b/cra-template/template/webpack.config.js new file mode 100644 index 0000000000..4362cbf807 --- /dev/null +++ b/cra-template/template/webpack.config.js @@ -0,0 +1,107 @@ +const HTMLWebpackPlugin = require('html-webpack-plugin'); +const CopyWebpackPlugin = require('copy-webpack-plugin'); +const TerserPlugin = require('terser-webpack-plugin'); + +const path = require('path'); +module.exports = function(webpackEnv) { + const isEnvProduction = webpackEnv === 'production'; + return { + entry: './src/index.js', + output: { + publicPath: '/', + path: isEnvProduction ? path.join(__dirname, '/build') : undefined, + pathinfo: !isEnvProduction, + filename: isEnvProduction ? 'static/js/[name].[contenthash:8].js' : 'static/js/bundle.[name].js', + // There are also additional JS chunk files if you use code splitting. + chunkFilename: isEnvProduction ? 'static/js/[name].[contenthash:8].chunk.js' : 'static/js/[name].chunk.js', + globalObject: 'this' + }, + plugins: [ + // copy luigi core resources to runtime directory + new CopyWebpackPlugin({ + patterns: [ + { + context: 'public', + to: 'index.html', + from: 'index.html' + }, + { + context: 'public', + to: 'luigi-config.js', + from: 'luigi-config.js' + }, + { + from: 'node_modules/@luigi-project/core', + to: './luigi-core' + } + ] + }), + // copy and inject the resulting webpack bundle to sampleapp.html instead of index.html + new HTMLWebpackPlugin( + Object.assign( + {}, + { + inject: true, + template: './public/sampleapp.html', + filename: 'sampleapp.html' + }, + isEnvProduction + ? { + minify: { + removeComments: true, + collapseWhitespace: true, + removeRedundantAttributes: true, + useShortDoctype: true, + removeEmptyAttributes: true, + removeStyleLinkTypeAttributes: true, + keepClosingSlash: true, + minifyJS: true, + minifyCSS: true, + minifyURLs: true + } + } + : undefined + ) + ) + ], + module: { + rules: [ + { + test: /\.js$/, + exclude: /node_modules/, + use: { + loader: 'babel-loader', + options: { + presets: [ + ['@babel/preset-env', { targets: 'defaults' }], + ['@babel/preset-react', { runtime: 'automatic' }] + ] + } + } + } + ] + }, + devServer: { + historyApiFallback: true, + hot: true, + port: 3000, + open: true + }, + optimization: { + minimize: true, + // todo: Remove after renaming luigi core map files + minimizer: [ + new TerserPlugin({ + exclude: /\.svelte\.map\.js$/ + }) + ] + }, + devtool: !isEnvProduction ? 'inline-source-map' : false, + // Change accordingly on prodcuciton + performance: { + hints: false, + maxEntrypointSize: 512000, + maxAssetSize: 512000 + } + }; +};