Introduce vite (#2677)
Co-authored-by: Krzysztof Żuraw <9116238+krzysztofzuraw@users.noreply.github.com>
This commit is contained in:
parent
ea2cd5fe96
commit
aa10a1d08e
12 changed files with 2633 additions and 6199 deletions
|
@ -15,9 +15,11 @@
|
|||
"cypress",
|
||||
"chai-friendly",
|
||||
"formatjs",
|
||||
"react-hooks"
|
||||
"react-hooks",
|
||||
"react-refresh"
|
||||
],
|
||||
"rules": {
|
||||
"react-refresh/only-export-components": "warn",
|
||||
"@typescript-eslint/adjacent-overload-signatures": "error",
|
||||
"@typescript-eslint/array-type": [
|
||||
"error",
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
FROM node:18-alpine as builder
|
||||
WORKDIR /app
|
||||
COPY package*.json ./
|
||||
COPY scripts/patchReactVirtualized.js scripts/
|
||||
RUN npm ci --legacy-peer-deps
|
||||
|
||||
COPY nginx/ nginx/
|
||||
COPY assets/ assets/
|
||||
COPY locale/ locale/
|
||||
COPY testUtils testUtils/
|
||||
COPY scripts/removeSourcemaps.js scripts/
|
||||
COPY codegen.yml ./
|
||||
COPY webpack.config.js ./
|
||||
COPY vite.config.js ./
|
||||
COPY tsconfig.json ./
|
||||
COPY *.d.ts ./
|
||||
COPY schema.graphql ./
|
||||
|
|
|
@ -86,7 +86,7 @@ Create `.env` file in a root directory or set environment variables with followi
|
|||
To start the development server run:
|
||||
|
||||
```
|
||||
$ npm start
|
||||
$ npm run dev
|
||||
```
|
||||
|
||||
In case you see CORS errors make sure to check [CORS configuration](https://docs.saleor.io/docs/3.x/developer/running-saleor/configuration#allowed_client_hosts) of your Saleor instance or CORS settings in the Cloud Console.
|
||||
|
|
8421
package-lock.json
generated
8421
package-lock.json
generated
File diff suppressed because it is too large
Load diff
31
package.json
31
package.json
|
@ -173,7 +173,6 @@
|
|||
"file-loader": "^5.0.2",
|
||||
"fork-ts-checker-webpack-plugin": "^3.1.1",
|
||||
"graphql-request": "^3.7.0",
|
||||
"html-webpack-plugin": "^3.2.0",
|
||||
"husky": "^4.3.0",
|
||||
"identity-obj-proxy": "^3.0.0",
|
||||
"jest": "^24.8.0",
|
||||
|
@ -195,22 +194,20 @@
|
|||
"require-context.macro": "^1.1.1",
|
||||
"rimraf": "^3.0.0",
|
||||
"setup-polly-jest": "^0.9.1",
|
||||
"speed-measure-webpack-plugin": "^1.5.0",
|
||||
"start-server-and-test": "^1.11.0",
|
||||
"ts-jest": "^27.0.7",
|
||||
"tsconfig-paths-webpack-plugin": "^3.2.0",
|
||||
"typescript": "^4.8.4",
|
||||
"webpack": "^4.35.3",
|
||||
"webpack-bundle-analyzer": "^4.4.1",
|
||||
"webpack-cli": "^3.3.6",
|
||||
"webpack-dev-server": "^3.11.0",
|
||||
"webpack-manifest-plugin": "2.2.0",
|
||||
"workbox-cacheable-response": "^6.1.2",
|
||||
"workbox-expiration": "^6.1.2",
|
||||
"workbox-precaching": "^6.1.2",
|
||||
"workbox-routing": "^6.1.2",
|
||||
"workbox-strategies": "^6.1.2",
|
||||
"workbox-webpack-plugin": "^6.1.2"
|
||||
"vite": "^3.2.4",
|
||||
"vite-plugin-html": "^3.2.0",
|
||||
"vite-plugin-sentry": "^1.1.6",
|
||||
"vite-plugin-swc-react-refresh": "^2.2.1",
|
||||
"eslint-plugin-react-refresh": "^0.3.1",
|
||||
"tsconfig-paths-webpack-plugin": "^3.2.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"fsevents": "^1.2.9"
|
||||
|
@ -255,6 +252,9 @@
|
|||
"pre-push": "npm run check-types"
|
||||
}
|
||||
},
|
||||
"overrides": {
|
||||
"resolve": "1.20.0"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{ts,tsx}": [
|
||||
"eslint --fix",
|
||||
|
@ -266,10 +266,12 @@
|
|||
]
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "vite --host",
|
||||
"build": "cross-env NODE_OPTIONS=--max_old_space_size=16384 vite build",
|
||||
"preview": "vite preview",
|
||||
"build-storybook": "cross-env NODE_OPTIONS=--openssl-legacy-provider build-storybook -c src/storybook/ -o build/storybook",
|
||||
"build-types": "graphql-codegen",
|
||||
"prebuild": "npm run build-types",
|
||||
"build": "cross-env NODE_OPTIONS=--openssl-legacy-provider webpack -p",
|
||||
"check-strict-null-errors": "tsc --noEmit --strictNullChecks | node scripts/count-strict-null-check-errors.js",
|
||||
"check-types": "tsc --noEmit",
|
||||
"extract-json-messages": "formatjs extract 'src/**/*.{ts,tsx}' --out-file locale/defaultMessages.json --format scripts/formatter.js",
|
||||
|
@ -278,7 +280,6 @@
|
|||
"heroku-postbuild": "npm run build",
|
||||
"serve:lhci": "cross-env NODE_ENV=production npm run server",
|
||||
"prestart": "npm run build-types",
|
||||
"start": "cross-env NODE_OPTIONS=--openssl-legacy-provider webpack-dev-server -d",
|
||||
"storybook": "cross-env NODE_OPTIONS=--openssl-legacy-provider start-storybook -p 3000 -c src/storybook/",
|
||||
"cy:run": "cypress run",
|
||||
"cy:run:dashboard": "cypress run --record",
|
||||
|
@ -288,10 +289,12 @@
|
|||
"cy:run:critical:parallel": "cypress run --record --env grepTags=@critical --parallel --tag Critical",
|
||||
"cy:run:allEnv:parallel": "cypress run --record --env grepTags=@allEnv --parallel",
|
||||
"cy:run:stable:parallel": "cypress run --record --env grepTags=@critical --parallel --tag Stable",
|
||||
"test": "TZ=UTC jest src/",
|
||||
"test": "TZ=UTC NODE_ENV=test jest src/",
|
||||
"lint": "npx eslint \"src/**/*.@(tsx|ts|jsx|js)\" --fix ; npx prettier --check \"src/**/*.@(tsx|ts|jsx|js)\" --write",
|
||||
"postbuild": "rimraf ./build/**/*.js.map",
|
||||
"postbuild": "node scripts/removeSourcemaps.js",
|
||||
"postinstall": "node scripts/patchReactVirtualized.js",
|
||||
"predev": "npm run build-types",
|
||||
"release": "release-it"
|
||||
},
|
||||
"description": ""
|
||||
}
|
||||
}
|
18
scripts/patchReactVirtualized.js
Normal file
18
scripts/patchReactVirtualized.js
Normal file
|
@ -0,0 +1,18 @@
|
|||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
const fs = require("fs");
|
||||
|
||||
/*
|
||||
react-virtualized has broken ESM file, we need to patch this manually:
|
||||
Ref: https://github.com/vitejs/vite/issues/1652#issuecomment-765875146
|
||||
*/
|
||||
|
||||
const dep =
|
||||
"node_modules/react-virtualized/dist/es/WindowScroller/utils/onScroll.js";
|
||||
const code = fs
|
||||
.readFileSync(dep, "utf-8")
|
||||
.replace(
|
||||
'import { bpfrpt_proptype_WindowScroller } from "../WindowScroller.js";',
|
||||
"",
|
||||
);
|
||||
|
||||
fs.writeFileSync(dep, code);
|
16
scripts/removeSourcemaps.js
Normal file
16
scripts/removeSourcemaps.js
Normal file
|
@ -0,0 +1,16 @@
|
|||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
/* eslint-disable no-console */
|
||||
const rimraf = require("rimraf");
|
||||
|
||||
/*
|
||||
When the sentry is enabled, remove sourcemaps
|
||||
*/
|
||||
|
||||
if (
|
||||
process.env.SENTRY_ORG &&
|
||||
process.env.SENTRY_PROJECT &&
|
||||
process.env.SENTRY_DSN &&
|
||||
process.env.SENTRY_AUTH_TOKEN
|
||||
) {
|
||||
rimraf("./build/**/*.js.map", () => console.log("Source maps removed."));
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
import {
|
||||
ApolloError,
|
||||
ApolloQueryResult,
|
||||
LazyQueryHookOptions as BaseLazyQueryHookOptions,
|
||||
OperationVariables,
|
||||
QueryHookOptions as BaseQueryHookOptions,
|
||||
QueryResult,
|
||||
useQuery as useBaseQuery,
|
||||
|
@ -18,7 +20,7 @@ import { useIntl } from "react-intl";
|
|||
|
||||
import useAppState from "./useAppState";
|
||||
import useNotifier from "./useNotifier";
|
||||
export { useLazyQuery, LazyQueryHookOptions } from "@apollo/client";
|
||||
export { useLazyQuery } from "@apollo/client";
|
||||
|
||||
const getPermissionKey = (permission: string) =>
|
||||
`PERMISSION_${permission}` as PrefixedPermissions;
|
||||
|
@ -51,6 +53,11 @@ export interface LoadMore<TData, TVariables> {
|
|||
) => Promise<ApolloQueryResult<TData>>;
|
||||
}
|
||||
|
||||
export type LazyQueryHookOptions<
|
||||
TData = any,
|
||||
TVariables = OperationVariables
|
||||
> = BaseLazyQueryHookOptions<TData, TVariables>;
|
||||
|
||||
export type UseQueryResult<TData, TVariables> = QueryResult<TData, TVariables> &
|
||||
LoadMore<TData, TVariables>;
|
||||
export type QueryHookOptions<TData, TVariables> = Partial<
|
||||
|
@ -60,6 +67,7 @@ export type QueryHookOptions<TData, TVariables> = Partial<
|
|||
variables?: Omit<TVariables, PrefixedPermissions>;
|
||||
}
|
||||
>;
|
||||
|
||||
type UseQueryHook<TData, TVariables> = (
|
||||
opts?: QueryHookOptions<TData, Omit<TVariables, PrefixedPermissions>>,
|
||||
) => UseQueryResult<TData, TVariables>;
|
||||
|
|
|
@ -10,8 +10,8 @@
|
|||
<title>Saleor e-commerce</title>
|
||||
<script>
|
||||
window.__SALEOR_CONFIG__ = {
|
||||
API_URL: "<%= API_URL %>",
|
||||
APP_MOUNT_URI: "<%= APP_MOUNT_URI %>",
|
||||
API_URL: "<%- API_URL %>",
|
||||
APP_MOUNT_URI: "<%- APP_MOUNT_URI %>",
|
||||
};
|
||||
</script>
|
||||
</head>
|
||||
|
|
0
webpack.d.ts → types.d.ts
vendored
0
webpack.d.ts → types.d.ts
vendored
138
vite.config.js
Normal file
138
vite.config.js
Normal file
|
@ -0,0 +1,138 @@
|
|||
/* eslint-disable no-console */
|
||||
import path from "path";
|
||||
import { defineConfig, loadEnv } from "vite";
|
||||
import { createHtmlPlugin } from "vite-plugin-html";
|
||||
import viteSentry from "vite-plugin-sentry";
|
||||
import { swcReactRefresh } from "vite-plugin-swc-react-refresh";
|
||||
|
||||
export default defineConfig(({ command, mode }) => {
|
||||
const env = loadEnv(mode, process.cwd(), "");
|
||||
/*
|
||||
Using explicit env variables, there is no need to expose all of them (security).
|
||||
*/
|
||||
const {
|
||||
NODE_ENV,
|
||||
API_URI,
|
||||
SW_INTERVAL,
|
||||
IS_CLOUD_INSTANCE,
|
||||
MARKETPLACE_URL,
|
||||
SALEOR_APPS_ENDPOINT,
|
||||
APP_MOUNT_URI,
|
||||
SENTRY_ORG,
|
||||
SENTRY_PROJECT,
|
||||
SENTRY_AUTH_TOKEN,
|
||||
SENTRY_DSN,
|
||||
ENVIRONMENT,
|
||||
STATIC_URL,
|
||||
} = env;
|
||||
|
||||
const enableSentry =
|
||||
SENTRY_ORG && SENTRY_PROJECT && SENTRY_DSN && SENTRY_AUTH_TOKEN;
|
||||
|
||||
const plugins = [
|
||||
swcReactRefresh(),
|
||||
createHtmlPlugin({
|
||||
entry: "/index.tsx",
|
||||
template: "index.html",
|
||||
inject: {
|
||||
data: {
|
||||
API_URL: API_URI,
|
||||
APP_MOUNT_URI,
|
||||
},
|
||||
},
|
||||
}),
|
||||
];
|
||||
|
||||
if (enableSentry) {
|
||||
console.log("Enabling sentry...");
|
||||
|
||||
plugins.push(
|
||||
viteSentry({
|
||||
sourceMaps: {
|
||||
include: "./build/dashboard",
|
||||
urlPrefix: process.env.SENTRY_URL_PREFIX,
|
||||
},
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
"qs" package uses 'get-intrinsic' whish refers to the global object, we need to recreate it.
|
||||
Issue presents only on development mode.
|
||||
*/
|
||||
const globals = command !== "build" ? { global: {} } : {};
|
||||
|
||||
return {
|
||||
root: "src",
|
||||
base: STATIC_URL ?? "/",
|
||||
envDir: "..",
|
||||
server: {
|
||||
port: 9000,
|
||||
},
|
||||
define: {
|
||||
...globals,
|
||||
|
||||
/*
|
||||
We still have references to process.env, we need to peserve them as workaround.
|
||||
*/
|
||||
"process.env": {
|
||||
NODE_ENV,
|
||||
API_URI,
|
||||
SW_INTERVAL,
|
||||
IS_CLOUD_INSTANCE,
|
||||
MARKETPLACE_URL,
|
||||
SALEOR_APPS_ENDPOINT,
|
||||
APP_MOUNT_URI,
|
||||
SENTRY_DSN,
|
||||
ENVIRONMENT,
|
||||
},
|
||||
},
|
||||
build: {
|
||||
minify: false,
|
||||
sourcemap: true,
|
||||
emptyOutDir: true,
|
||||
outDir: "../build/dashboard",
|
||||
assetsDir: ".",
|
||||
commonjsOptions: {
|
||||
/*
|
||||
Fix dynamic imports by "require", Necessary for react-editor-js
|
||||
Ref: https://github.com/Jungwoo-An/react-editor-js/blob/e58b7ba5e66d07912bb78f65ac911e4018d363e1/packages/react-editor-js/src/factory.ts#L5
|
||||
*/
|
||||
transformMixedEsModules: true,
|
||||
},
|
||||
},
|
||||
optimizeDeps: {
|
||||
include: ["esm-dep > cjs-dep"],
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
/*
|
||||
Aliases from tsconfig, we need to preserve them.
|
||||
Since @saleor points to "src", we need to add aliases for macaw and sdk as first.
|
||||
*/
|
||||
"@saleor/macaw-ui": path.resolve(
|
||||
__dirname,
|
||||
"node_modules/@saleor/macaw-ui",
|
||||
),
|
||||
"@saleor/app-sdk": path.resolve(
|
||||
__dirname,
|
||||
"node_modules/@saleor/app-sdk",
|
||||
),
|
||||
"@saleor/sdk": path.resolve(__dirname, "node_modules/@saleor/sdk"),
|
||||
"@saleor": path.resolve(__dirname, "./src"),
|
||||
"@assets": path.resolve(__dirname, "./assets"),
|
||||
"@locale": path.resolve(__dirname, "./locale"),
|
||||
src: path.resolve(__dirname, "./src"),
|
||||
|
||||
/*
|
||||
Moment.js/react-moment does not fully suport ES modules.
|
||||
Vite resolves it by using jsnext:main https://github.com/moment/moment/blob/develop/package.json#L26.
|
||||
We enforce to use a different path, ignoring jsnext:main field.
|
||||
*/
|
||||
moment: path.resolve(__dirname, "./node_modules/moment/moment.js"),
|
||||
},
|
||||
},
|
||||
plugins,
|
||||
esbuild: { jsx: "automatic" },
|
||||
};
|
||||
});
|
|
@ -1,184 +0,0 @@
|
|||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
const path = require("path");
|
||||
const CheckerPlugin = require("fork-ts-checker-webpack-plugin");
|
||||
const webpack = require("webpack");
|
||||
const TsconfigPathsPlugin = require("tsconfig-paths-webpack-plugin");
|
||||
const HtmlWebpackPlugin = require("html-webpack-plugin");
|
||||
const { InjectManifest } = require("workbox-webpack-plugin");
|
||||
const SentryWebpackPlugin = require("@sentry/webpack-plugin");
|
||||
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer")
|
||||
.BundleAnalyzerPlugin;
|
||||
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");
|
||||
|
||||
require("dotenv").config();
|
||||
|
||||
const resolve = path.resolve.bind(path, __dirname);
|
||||
|
||||
let bundleAnalyzerPlugin;
|
||||
let speedMeasureWrapper = fn => fn;
|
||||
const analyze = process.env.ANALYZE;
|
||||
if (!!analyze) {
|
||||
const smp = new SpeedMeasurePlugin();
|
||||
speedMeasureWrapper = smp.wrap;
|
||||
bundleAnalyzerPlugin = new BundleAnalyzerPlugin();
|
||||
}
|
||||
|
||||
const pathsPlugin = new TsconfigPathsPlugin({
|
||||
configFile: "./tsconfig.json",
|
||||
});
|
||||
|
||||
const checkerPlugin = new CheckerPlugin({
|
||||
eslint: true,
|
||||
reportFiles: ["src/**/*.{ts,tsx}"],
|
||||
});
|
||||
const htmlWebpackPlugin = new HtmlWebpackPlugin({
|
||||
filename: "index.html",
|
||||
hash: true,
|
||||
template: "./src/index.html",
|
||||
templateParameters: {
|
||||
// URI is kept for backwards compatibility.
|
||||
// See more at https://github.com/saleor/saleor-dashboard/issues/2502
|
||||
API_URL: process.env.API_URI,
|
||||
APP_MOUNT_URI: process.env.APP_MOUNT_URI,
|
||||
},
|
||||
});
|
||||
const environmentPlugin = new webpack.EnvironmentPlugin({
|
||||
MARKETPLACE_URL: "",
|
||||
SALEOR_APPS_ENDPOINT: "",
|
||||
DEMO_MODE: false,
|
||||
ENVIRONMENT: "",
|
||||
GTM_ID: "",
|
||||
SENTRY_DSN: "",
|
||||
SW_INTERVAL: "300", // Fetch SW every 300 seconds
|
||||
IS_CLOUD_INSTANCE: false,
|
||||
});
|
||||
|
||||
const dashboardBuildPath = "build/dashboard/";
|
||||
|
||||
module.exports = speedMeasureWrapper((env, argv) => {
|
||||
const devMode = argv.mode !== "production";
|
||||
|
||||
let fileLoaderPath;
|
||||
let output;
|
||||
|
||||
if (!process.env.API_URI) {
|
||||
throw new Error("Environment variable API_URI not set");
|
||||
}
|
||||
|
||||
const publicPath = process.env.STATIC_URL || "/";
|
||||
if (!devMode) {
|
||||
output = {
|
||||
chunkFilename: "[name].[chunkhash].js",
|
||||
filename: "[name].[chunkhash].js",
|
||||
path: resolve(dashboardBuildPath),
|
||||
publicPath,
|
||||
};
|
||||
fileLoaderPath = "file-loader?name=[name].[hash].[ext]";
|
||||
} else {
|
||||
output = {
|
||||
chunkFilename: "[name].js",
|
||||
filename: "[name].js",
|
||||
path: resolve(dashboardBuildPath),
|
||||
publicPath,
|
||||
};
|
||||
fileLoaderPath = "file-loader?name=[name].[ext]";
|
||||
}
|
||||
|
||||
// Create release if sentry config is set
|
||||
let sentryPlugin;
|
||||
if (
|
||||
!devMode &&
|
||||
process.env.SENTRY_ORG &&
|
||||
process.env.SENTRY_PROJECT &&
|
||||
process.env.SENTRY_DSN &&
|
||||
process.env.SENTRY_AUTH_TOKEN
|
||||
) {
|
||||
sentryPlugin = new SentryWebpackPlugin({
|
||||
include: "./build/dashboard/",
|
||||
urlPrefix: process.env.SENTRY_URL_PREFIX,
|
||||
});
|
||||
}
|
||||
|
||||
let manifestPlugin;
|
||||
if (!devMode) {
|
||||
manifestPlugin = new InjectManifest({
|
||||
swSrc: "./src/sw.js",
|
||||
swDest: "sw.js",
|
||||
maximumFileSizeToCacheInBytes: 5000000,
|
||||
webpackCompilationPlugins: [checkerPlugin],
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
devServer: {
|
||||
compress: true,
|
||||
contentBase: path.join(__dirname, dashboardBuildPath),
|
||||
historyApiFallback: true,
|
||||
hot: true,
|
||||
port: 9000,
|
||||
},
|
||||
devtool: devMode ? "cheap-module-source-map" : "source-map",
|
||||
entry: {
|
||||
dashboard: "./src/index.tsx",
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.(jsx?|tsx?)$/,
|
||||
use: [
|
||||
{
|
||||
loader: "esbuild-loader",
|
||||
options: {
|
||||
loader: "tsx",
|
||||
target: "es2015",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.css$/i,
|
||||
use: ["style-loader", "css-loader"],
|
||||
},
|
||||
{
|
||||
include: [
|
||||
resolve("node_modules"),
|
||||
resolve("assets/fonts"),
|
||||
resolve("assets/images"),
|
||||
resolve("assets/favicons"),
|
||||
],
|
||||
loader: fileLoaderPath,
|
||||
test: /\.(eot|otf|png|svg|jpg|ttf|woff|woff2)(\?v=[0-9.]+)?$/,
|
||||
},
|
||||
],
|
||||
},
|
||||
optimization: {
|
||||
removeAvailableModules: false,
|
||||
removeEmptyChunks: false,
|
||||
splitChunks: false,
|
||||
},
|
||||
output,
|
||||
plugins: [
|
||||
checkerPlugin,
|
||||
environmentPlugin,
|
||||
htmlWebpackPlugin,
|
||||
sentryPlugin,
|
||||
manifestPlugin,
|
||||
bundleAnalyzerPlugin,
|
||||
].filter(Boolean),
|
||||
resolve: {
|
||||
// Resolve macaw ui's peer dependencies to our own node_modules
|
||||
// to make it work with npm link
|
||||
alias: {
|
||||
react: path.resolve("./node_modules/react"),
|
||||
"react-dom": path.resolve("./node_modules/react-dom"),
|
||||
"@material-ui/core": path.resolve("./node_modules/@material-ui/core"),
|
||||
"@material-ui/icons": path.resolve("./node_modules/@material-ui/icons"),
|
||||
"@material-ui/styles": path.resolve(
|
||||
"./node_modules/@material-ui/styles",
|
||||
),
|
||||
},
|
||||
extensions: [".js", ".jsx", ".ts", ".tsx"],
|
||||
plugins: [pathsPlugin],
|
||||
},
|
||||
};
|
||||
});
|
Loading…
Reference in a new issue