feat: swc register (#1779)

* feat: implements esbuild and removes babel

* chore: implements esbuild-register

* chore: tests passing

* chore: implements @swc/jest for tests

* feat: implements swc

* chore: removes build and relies on swc/register only

* chore: converts some exports

* chore: flattens ts configs

* chore: allows tsx in swc

* chore: converts more exports into js

* chore: restores payload module.exports

* chore: removes unused dependency
This commit is contained in:
James Mikrut
2023-01-04 10:11:26 -05:00
committed by GitHub
parent 82501319ce
commit c11bcd1416
37 changed files with 345 additions and 2065 deletions

View File

@@ -1,3 +0,0 @@
const config = require('./src/babel.config');
module.exports = config;

View File

@@ -1,3 +0,0 @@
const babelConfig = require('./dist/babel.config');
exports.config = babelConfig;

8
components/elements.js Normal file
View File

@@ -0,0 +1,8 @@
exports.Button = require('../dist/admin/components/elements/Button');
exports.Card = require('../dist/admin/components/elements/Card');
exports.Eyebrow = require('../dist/admin/components/elements/Eyebrow');
exports.Nav = require('../dist/admin/components/elements/Nav');
const { Gutter } = require('../dist/admin/components/elements/Gutter');
exports.Gutter = Gutter;

View File

@@ -1,5 +0,0 @@
export { default as Button } from '../dist/admin/components/elements/Button';
export { default as Card } from '../dist/admin/components/elements/Card';
export { default as Eyebrow } from '../dist/admin/components/elements/Eyebrow';
export { default as Nav } from '../dist/admin/components/elements/Nav';
export { Gutter } from '../dist/admin/components/elements/Gutter';

38
components/forms.js Normal file
View File

@@ -0,0 +1,38 @@
const {
useForm,
/**
* @deprecated useWatchForm is no longer preferred. If you need all form fields, prefer `useAllFormFields`.
*/
useWatchForm,
useFormFields,
useAllFormFields,
useFormSubmitted,
useFormProcessing,
useFormModified,
} = require('../dist/admin/components/forms/Form/context');
const useField = require('../dist/admin/components/forms/useField');
exports.useForm = useForm;
exports.useWatchForm = useWatchForm;
exports.useFormFields = useFormFields;
exports.useAllFormField = useAllFormFields;
exports.useFormSubmitted = useFormSubmitted;
exports.useFormProcessing = useFormProcessing;
exports.useFormModified = useFormModified;
exports.useField = useField;
exports.useFieldType = useField;
exports.Form = require('../dist/admin/components/forms/Form');
exports.Text = require('../dist/admin/components/forms/field-types/Text');
exports.TextInput = require('../dist/admin/components/forms/field-types/Text/Input');
exports.Group = require('../dist/admin/components/forms/field-types/Group');
exports.Select = require('../dist/admin/components/forms/field-types/Select');
exports.SelectInput = require('../dist/admin/components/forms/field-types/Select/Input');
exports.Checkbox = require('../dist/admin/components/forms/field-types/Checkbox');
exports.Submit = require('../dist/admin/components/forms/Submit');
exports.Label = require('../dist/admin/components/forms/Label');
exports.reduceFieldsToValues = require('../dist/admin/components/forms/Form/reduceFieldsToValues');
exports.getSiblingData = require('../dist/admin/components/forms/Form/getSiblingData');
exports.withCondition = require('../dist/admin/components/forms/withCondition');

View File

@@ -1,38 +0,0 @@
export {
useForm,
/**
* @deprecated useWatchForm is no longer preferred. If you need all form fields, prefer `useAllFormFields`.
*/
useWatchForm,
useFormFields,
useAllFormFields,
useFormSubmitted,
useFormProcessing,
useFormModified,
} from '../dist/admin/components/forms/Form/context';
export { default as useField } from '../dist/admin/components/forms/useField';
/**
* @deprecated This method is now called useField. The useFieldType alias will be removed in an upcoming version.
*/
export { default as useFieldType } from '../dist/admin/components/forms/useField';
export { default as Form } from '../dist/admin/components/forms/Form';
export { default as Text } from '../dist/admin/components/forms/field-types/Text';
export { default as TextInput } from '../dist/admin/components/forms/field-types/Text/Input';
export { default as Group } from '../dist/admin/components/forms/field-types/Group';
export { default as Select } from '../dist/admin/components/forms/field-types/Select';
export { default as SelectInput } from '../dist/admin/components/forms/field-types/Select/Input';
export { default as Checkbox } from '../dist/admin/components/forms/field-types/Checkbox';
export { default as Submit } from '../dist/admin/components/forms/Submit';
export { default as Label } from '../dist/admin/components/forms/Label';
export { default as reduceFieldsToValues } from '../dist/admin/components/forms/Form/reduceFieldsToValues';
export { default as getSiblingData } from '../dist/admin/components/forms/Form/getSiblingData';
export { default as withCondition } from '../dist/admin/components/forms/withCondition';

3
components/hooks.js Normal file
View File

@@ -0,0 +1,3 @@
const { useStepNav } = require('../dist/admin/components/elements/StepNav');
exports.useStepNav = useStepNav;

View File

@@ -1 +0,0 @@
export { useStepNav } from '../dist/admin/components/elements/StepNav';

View File

@@ -0,0 +1,3 @@
const { usePreferences } = require('../dist/admin/components/utilities/Preferences');
exports.usePreferences = usePreferences;

View File

@@ -1 +0,0 @@
export { usePreferences } from '../dist/admin/components/utilities/Preferences';

3
components/rich-text.js Normal file
View File

@@ -0,0 +1,3 @@
exports.LeafButton = require('../dist/admin/components/forms/field-types/RichText/leaves/Button');
exports.ElementButton = require('../dist/admin/components/forms/field-types/RichText/elements/Button');
exports.toggleElement = require('../dist/admin/components/forms/field-types/RichText/elements/toggle');

View File

@@ -1,3 +0,0 @@
export { default as LeafButton } from '../dist/admin/components/forms/field-types/RichText/leaves/Button';
export { default as ElementButton } from '../dist/admin/components/forms/field-types/RichText/elements/Button';
export { default as toggleElement } from '../dist/admin/components/forms/field-types/RichText/elements/toggle';

2
components/templates.js Normal file
View File

@@ -0,0 +1,2 @@
exports.DefaultTemplate = require('../dist/admin/components/templates/Default');
exports.MinimalTemplate = require('../dist/admin/components/templates/Minimal');

View File

@@ -1,2 +0,0 @@
export { default as DefaultTemplate } from '../dist/admin/components/templates/Default';
export { default as MinimalTemplate } from '../dist/admin/components/templates/Minimal';

13
components/utilities.js Normal file
View File

@@ -0,0 +1,13 @@
exports.Meta = require('../dist/admin/components/utilities/Meta');
const { useLocale } = require('../dist/admin/components/utilities/Locale');
const { useDocumentInfo } = require('../dist/admin/components/utilities/DocumentInfo');
const { useConfig } = require('../dist/admin/components/utilities/Config');
const { useAuth } = require('../dist/admin/components/utilities/Auth');
const { useEditDepth } = require('../dist/admin/components/utilities/EditDepth');
exports.useLocale = useLocale;
exports.useDocumentInfo = useDocumentInfo;
exports.useConfig = useConfig;
exports.useAuth = useAuth;
exports.useEditDepth = useEditDepth;

View File

@@ -1,6 +0,0 @@
export { default as Meta } from '../dist/admin/components/utilities/Meta';
export { useLocale } from '../dist/admin/components/utilities/Locale';
export { useDocumentInfo } from '../dist/admin/components/utilities/DocumentInfo';
export { useConfig } from '../dist/admin/components/utilities/Config';
export { useAuth } from '../dist/admin/components/utilities/Auth';
export { useEditDepth } from '../dist/admin/components/utilities/EditDepth';

View File

@@ -3,6 +3,9 @@ module.exports = {
testTimeout: 15000,
testRegex: '(/src/admin/.*\\.(test|spec))\\.[jt]sx?$',
setupFilesAfterEnv: ['<rootDir>/test/componentsSetup.js'],
transform: {
'^.+\\.(t|j)sx?$': ['@swc/jest'],
},
testPathIgnorePatterns: [
'node_modules',
'dist',

View File

@@ -5,6 +5,9 @@ module.exports = {
'**/src/**/*.spec.ts',
'**/test/**/*int.spec.ts',
],
transform: {
'^.+\\.(t|j)sx?$': ['@swc/jest'],
},
globalSetup: './test/jest.setup.ts',
testTimeout: 90000,
moduleNameMapper: {

View File

@@ -32,7 +32,7 @@
},
"scripts": {
"copyfiles": "copyfiles -u 1 \"src/**/*.{html,css,scss,ttf,woff,woff2,eot,svg,jpg,png}\" dist/",
"build:tsc": "tsc --p tsconfig.admin.json && tsc --p tsconfig.server.json",
"build:tsc": "tsc",
"build:components": "webpack --config dist/webpack/components.config.js",
"build": "yarn copyfiles && yarn build:tsc && yarn build:components",
"build:watch": "nodemon --watch 'src/**' --ext 'ts,tsx' --exec \"yarn build:tsc\"",
@@ -80,26 +80,15 @@
"auth"
],
"dependencies": {
"@babel/cli": "^7.12.8",
"@babel/core": "^7.11.6",
"@babel/node": "^7.12.6",
"@babel/plugin-proposal-class-properties": "^7.8.3",
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.14.2",
"@babel/plugin-transform-runtime": "^7.11.5",
"@babel/preset-env": "^7.8.3",
"@babel/preset-react": "^7.8.3",
"@babel/preset-typescript": "^7.12.1",
"@babel/register": "^7.11.5",
"@date-io/date-fns": "^2.10.6",
"@dnd-kit/core": "^6.0.5",
"@dnd-kit/sortable": "^7.0.1",
"@faceless-ui/modal": "^2.0.1",
"@faceless-ui/scroll-info": "^1.2.3",
"@faceless-ui/window-info": "^2.0.2",
"@swc/core": "^1.3.24",
"@swc/register": "^0.1.10",
"@monaco-editor/react": "^4.4.6",
"@types/sharp": "^0.26.1",
"babel-jest": "^26.3.0",
"babel-loader": "^8.1.0",
"body-parser": "^1.19.0",
"bson-objectid": "^2.0.1",
"compression": "^1.7.4",
@@ -189,6 +178,8 @@
"slate-hyperscript": "^0.66.0",
"slate-react": "^0.72.1",
"style-loader": "^2.0.0",
"swc-loader": "^0.2.3",
"swc-minify-webpack-plugin": "^1.0.1",
"terser-webpack-plugin": "^5.0.3",
"ts-essentials": "^7.0.1",
"url-loader": "^4.1.1",
@@ -203,13 +194,11 @@
"devDependencies": {
"@playwright/test": "^1.23.1",
"@release-it/conventional-changelog": "^5.1.1",
"@swc/jest": "^0.2.24",
"@testing-library/jest-dom": "^5.11.4",
"@testing-library/react": "^13.0.1",
"@trbl/eslint-config": "^1.2.4",
"@types/asap": "^2.0.0",
"@types/babel__core": "^7.1.12",
"@types/babel__plugin-transform-runtime": "^7.9.1",
"@types/babel__preset-env": "^7.9.1",
"@types/body-parser": "^1.19.0",
"@types/compression": "^1.7.0",
"@types/conf": "^3.0.0",
@@ -259,6 +248,7 @@
"@types/react-router-dom": "^5.1.6",
"@types/react-select": "^3.0.26",
"@types/sass": "^1.16.0",
"@types/sharp": "^0.26.1",
"@types/shelljs": "^0.8.11",
"@types/testing-library__jest-dom": "^5.9.5",
"@types/uuid": "^8.3.0",
@@ -269,8 +259,6 @@
"@types/webpack-hot-middleware": "2.25.3",
"@typescript-eslint/eslint-plugin": "^4.8.1",
"@typescript-eslint/parser": "4.0.1",
"babel-eslint": "^10.0.1",
"babel-plugin-ignore-html-and-css-imports": "^0.1.0",
"copyfiles": "^2.4.0",
"cross-env": "^7.0.2",
"eslint": "^6.8.0",

View File

@@ -1,21 +0,0 @@
module.exports = {
presets: [
require.resolve('@babel/preset-typescript'),
[
require.resolve('@babel/preset-env'),
{
targets: [
'defaults',
'not IE 11',
'not IE_Mob 11',
],
},
],
require.resolve('@babel/preset-react'),
],
plugins: [
require.resolve('@babel/plugin-transform-runtime'),
require.resolve('@babel/plugin-proposal-class-properties'),
require.resolve('@babel/plugin-proposal-nullish-coalescing-operator'),
],
};

View File

@@ -1,23 +1,17 @@
/* eslint-disable @typescript-eslint/no-var-requires */
/* eslint-disable global-require */
import webpack from 'webpack';
import getWebpackProdConfig from '../webpack/getProdConfig';
import findConfig from '../config/find';
import loadConfig from '../config/load';
const configPath = findConfig();
const rawConfigPath = findConfig();
export const build = (): void => {
export const build = async (): Promise<void> => {
try {
const config = loadConfig();
const webpackProdConfig = getWebpackProdConfig({
...config,
paths: {
...(config.paths || {}),
config: configPath,
},
});
const webpackProdConfig = getWebpackProdConfig(config);
webpack(webpackProdConfig, (err, stats) => { // Stats Object
if (err || stats.hasErrors()) {
@@ -35,7 +29,7 @@ export const build = (): void => {
});
} catch (err) {
console.error(err);
throw new Error(`Error: can't find the configuration file located at ${configPath}.`);
throw new Error(`Error: can't find the configuration file located at ${rawConfigPath}.`);
}
};

View File

@@ -2,12 +2,6 @@
import minimist from 'minimist';
import { generateTypes } from './generateTypes';
import { generateGraphQLSchema } from './generateGraphQLSchema';
import babelConfig from '../babel.config';
require('@babel/register')({
...babelConfig,
extensions: ['.ts', '.tsx', '.js', '.jsx'],
});
const { build } = require('./build');

View File

@@ -0,0 +1 @@
export const clientFiles = ['.scss', '.css', '.svg', '.png', '.jpg', '.eot', '.ttf', '.woff', '.woff2'];

View File

@@ -1,36 +1,36 @@
/* eslint-disable import/no-dynamic-require */
/* eslint-disable global-require */
// eslint-disable-next-line import/no-extraneous-dependencies
import swcRegister from '@swc/register';
import path from 'path';
import pino from 'pino';
import Logger from '../utilities/logger';
import { SanitizedConfig } from './types';
import findConfig from './find';
import validate from './validate';
import babelConfig from '../babel.config';
const removedExtensions = ['.scss', '.css', '.svg', '.png', '.jpg', '.eot', '.ttf', '.woff', '.woff2'];
import { clientFiles } from './clientFiles';
const loadConfig = (logger?: pino.Logger): SanitizedConfig => {
const localLogger = logger ?? Logger();
const configPath = findConfig();
removedExtensions.forEach((ext) => {
require.extensions[ext] = () => null;
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
swcRegister({
jsc: {
parser: {
syntax: 'typescript',
tsx: true,
},
},
module: {
type: 'commonjs',
},
});
// eslint-disable-next-line @typescript-eslint/no-var-requires
require('@babel/register')({
...babelConfig,
extensions: ['.ts', '.tsx', '.js', '.jsx'],
env: {
development: {
sourceMaps: 'inline',
retainLines: true,
},
},
ignore: [
/node_modules[\\/](?!.pnpm[\\/].*[\\/]node_modules[\\/])(?!payload[\\/]dist[\\/]admin|payload[\\/]components).*/,
],
clientFiles.forEach((ext) => {
require.extensions[ext] = () => null;
});
// eslint-disable-next-line @typescript-eslint/no-var-requires
@@ -38,14 +38,18 @@ const loadConfig = (logger?: pino.Logger): SanitizedConfig => {
if (config.default) config = config.default;
const validatedConfig = validate(config, localLogger);
let validatedConfig = config;
if (process.env.NODE_ENV !== 'production') {
validatedConfig = validate(config, localLogger);
}
return {
...validatedConfig,
paths: {
...(validatedConfig.paths || {}),
configDir: path.dirname(configPath),
config: configPath,
rawConfig: configPath,
},
};
};

View File

@@ -540,7 +540,11 @@ export type SanitizedConfig = Omit<
> & {
collections: SanitizedCollectionConfig[];
globals: SanitizedGlobalConfig[];
paths: { [key: string]: string };
paths: {
configDir: string
config: string
rawConfig: string
};
};
export type EntityDescription =

View File

@@ -248,7 +248,7 @@ export class Payload {
return restoreVersion(this, options);
}
login = async <T extends TypeWithID = any>(options: LoginOptions): Promise<LoginResult & { user: T}> => {
login = async <T extends TypeWithID = any>(options: LoginOptions): Promise<LoginResult & { user: T }> => {
const { login } = localOperations.auth;
return login(this, options);
}

View File

@@ -26,11 +26,13 @@ export default {
module: {
rules: [
{
test: /\.js$/,
test: /\.(t|j)sx?$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
use: [
{
loader: require.resolve('swc-loader'),
},
],
},
{
oneOf: [

View File

@@ -2,7 +2,6 @@ import path from 'path';
import HtmlWebpackPlugin from 'html-webpack-plugin';
import webpack, { Configuration } from 'webpack';
import { SanitizedConfig } from '../config/types';
import babelConfig from '../babel.config';
const mockModulePath = path.resolve(__dirname, './mocks/emptyModule.js');
const mockDotENVPath = path.resolve(__dirname, './mocks/dotENV.js');
@@ -20,11 +19,18 @@ export default (config: SanitizedConfig): Configuration => ({
rules: [
{
test: /\.(t|j)sx?$/,
exclude: /node_modules[\\/](?!(@payloadcms[\\/]payload)[\\/]).*/,
exclude: /node_modules/,
use: [
{
loader: require.resolve('babel-loader'),
options: babelConfig,
loader: require.resolve('swc-loader'),
options: {
jsc: {
parser: {
syntax: 'typescript',
tsx: true,
},
},
},
},
],
},
@@ -47,7 +53,7 @@ export default (config: SanitizedConfig): Configuration => ({
},
modules: ['node_modules', path.resolve(__dirname, '../../node_modules')],
alias: {
'payload-config': config.paths.config,
'payload-config': config.paths.rawConfig,
payload$: mockModulePath,
'payload-user-css': config.admin.css,
dotenv: mockDotENVPath,

View File

@@ -1,12 +1,13 @@
import TerserJSPlugin from 'terser-webpack-plugin';
import MiniCSSExtractPlugin from 'mini-css-extract-plugin';
import CssMinimizerPlugin from 'css-minimizer-webpack-plugin';
import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer';
import path from 'path';
import { Configuration } from 'webpack';
import { SanitizedConfig } from '../config/types';
import getBaseConfig from './getBaseConfig';
// eslint-disable-next-line import/no-extraneous-dependencies, @typescript-eslint/no-var-requires
const SwcMinifyWebpackPlugin = require('swc-minify-webpack-plugin');
export default (payloadConfig: SanitizedConfig): Configuration => {
const baseConfig = getBaseConfig(payloadConfig) as any;
@@ -21,7 +22,7 @@ export default (payloadConfig: SanitizedConfig): Configuration => {
mode: 'production',
stats: 'errors-only',
optimization: {
minimizer: [new TerserJSPlugin({}), new CssMinimizerPlugin()],
minimizer: [new SwcMinifyWebpackPlugin()],
splitChunks: {
cacheGroups: {
styles: {

View File

@@ -7,7 +7,7 @@ require('isomorphic-fetch');
let apiUrl;
const [ code, secret, name ] = [ 'test', 'strategy', 'Tester' ];
const [code, secret, name] = ['test', 'strategy', 'Tester'];
const headers = {
'Content-Type': 'application/json',
@@ -31,7 +31,7 @@ describe('AuthStrategies', () => {
body: JSON.stringify({
code,
secret,
name
name,
}),
headers,
method: 'post',
@@ -43,15 +43,14 @@ describe('AuthStrategies', () => {
headers: {
...headers,
code,
secret
secret,
},
});
const data = await response.json();
expect(response.status).toBe(200);
expect(data.user.name).toBe(name)
expect(data.user.name).toBe(name);
});
});
});

View File

@@ -1,17 +1,6 @@
const fs = require('fs');
const path = require('path');
const babelConfig = require('../babel.config');
require('@babel/register')({
...babelConfig,
extensions: ['.ts', '.tsx', '.js', '.jsx'],
env: {
development: {
sourceMaps: 'inline',
retainLines: true,
},
},
});
const { register } = require('esbuild-register/dist/node');
const [testSuiteDir] = process.argv.slice(2);
@@ -28,6 +17,11 @@ if (!fs.existsSync(configPath)) {
}
process.env.PAYLOAD_CONFIG_PATH = configPath;
process.env.PAYLOAD_DROP_DATABASE = 'true';
register({
platform: 'node',
});
require('./devServer');

View File

@@ -1,3 +1,4 @@
import express from 'express';
import { v4 as uuid } from 'uuid';
import payload from '../src';

View File

@@ -1,19 +1,7 @@
const path = require('path');
const fs = require('fs');
const babelConfig = require('../babel.config');
require('@babel/register')({
...babelConfig,
extensions: ['.ts', '.tsx', '.js', '.jsx'],
env: {
development: {
sourceMaps: 'inline',
retainLines: true,
},
},
});
const { generateTypes } = require('../src/bin/generateTypes');
const { generateTypes } = require('../dist/bin/generateTypes');
const [testConfigDir] = process.argv.slice(2);

View File

@@ -1,12 +0,0 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"module": "esnext"
},
"include": [
"src/admin"
],
"exclude": [
"**/*.spec.js",
]
}

View File

@@ -1,10 +0,0 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
},
"exclude": [
"src/admin",
"**/*.spec.js",
]
}

2027
yarn.lock

File diff suppressed because it is too large Load Diff