Replace Webpack with Vite (#4765)
Co-authored-by: Tom Moor <tom@getoutline.com> Co-authored-by: Vio <vio@beanon.com>
This commit is contained in:
@@ -25,26 +25,12 @@ import {
|
||||
import Fade from "./Fade";
|
||||
|
||||
const DocumentHistory = React.lazy(
|
||||
() =>
|
||||
import(
|
||||
/* webpackChunkName: "document-history" */
|
||||
"~/scenes/Document/components/History"
|
||||
)
|
||||
() => import("~/scenes/Document/components/History")
|
||||
);
|
||||
const DocumentInsights = React.lazy(
|
||||
() =>
|
||||
import(
|
||||
/* webpackChunkName: "document-insights" */
|
||||
"~/scenes/Document/components/Insights"
|
||||
)
|
||||
);
|
||||
const CommandBar = React.lazy(
|
||||
() =>
|
||||
import(
|
||||
/* webpackChunkName: "command-bar" */
|
||||
"~/components/CommandBar"
|
||||
)
|
||||
() => import("~/scenes/Document/components/Insights")
|
||||
);
|
||||
const CommandBar = React.lazy(() => import("~/components/CommandBar"));
|
||||
|
||||
const AuthenticatedLayout: React.FC = ({ children }) => {
|
||||
const { ui, auth } = useStores();
|
||||
|
||||
@@ -4,7 +4,7 @@ import * as React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { usePopoverState, PopoverDisclosure } from "reakit/Popover";
|
||||
import Document from "~/models/Document";
|
||||
import { AvatarWithPresence } from "~/components/Avatar";
|
||||
import AvatarWithPresence from "~/components/Avatar/AvatarWithPresence";
|
||||
import DocumentViews from "~/components/DocumentViews";
|
||||
import Facepile from "~/components/Facepile";
|
||||
import NudeButton from "~/components/NudeButton";
|
||||
|
||||
@@ -30,13 +30,7 @@ import { sharedDocumentPath } from "~/utils/routeHelpers";
|
||||
import { isHash } from "~/utils/urls";
|
||||
import DocumentBreadcrumb from "./DocumentBreadcrumb";
|
||||
|
||||
const LazyLoadedEditor = React.lazy(
|
||||
() =>
|
||||
import(
|
||||
/* webpackChunkName: "preload-shared-editor" */
|
||||
"~/editor"
|
||||
)
|
||||
);
|
||||
const LazyLoadedEditor = React.lazy(() => import("~/editor"));
|
||||
|
||||
export type Props = Optional<
|
||||
EditorProps,
|
||||
|
||||
@@ -30,7 +30,7 @@ class ErrorBoundary extends React.Component<Props> {
|
||||
if (
|
||||
this.props.reloadOnChunkMissing &&
|
||||
error.message &&
|
||||
error.message.match(/chunk/)
|
||||
error.message.match(/dynamically imported module/)
|
||||
) {
|
||||
// If the editor bundle fails to load then reload the entire window. This
|
||||
// can happen if a deploy happens between the user loading the initial JS
|
||||
@@ -60,7 +60,9 @@ class ErrorBoundary extends React.Component<Props> {
|
||||
if (this.error) {
|
||||
const error = this.error;
|
||||
const isReported = !!env.SENTRY_DSN && isCloudHosted;
|
||||
const isChunkError = this.error.message.match(/chunk/);
|
||||
const isChunkError = this.error.message.match(
|
||||
/dynamically imported module/
|
||||
);
|
||||
|
||||
if (isChunkError) {
|
||||
return (
|
||||
|
||||
@@ -53,11 +53,7 @@ const style = {
|
||||
};
|
||||
|
||||
const TwitterPicker = React.lazy(
|
||||
() =>
|
||||
import(
|
||||
/* webpackChunkName: "twitter-picker" */
|
||||
"react-color/lib/components/twitter/Twitter"
|
||||
)
|
||||
() => import("react-color/lib/components/twitter/Twitter")
|
||||
);
|
||||
|
||||
export const icons = {
|
||||
|
||||
@@ -5,13 +5,7 @@ import scrollIntoView from "smooth-scroll-into-view-if-needed";
|
||||
import useQuery from "~/hooks/useQuery";
|
||||
import type { Props } from "./Table";
|
||||
|
||||
const Table = React.lazy(
|
||||
() =>
|
||||
import(
|
||||
/* webpackChunkName: "table" */
|
||||
"~/components/Table"
|
||||
)
|
||||
);
|
||||
const Table = React.lazy(() => import("~/components/Table"));
|
||||
|
||||
const TableFromParams = (
|
||||
props: Omit<Props, "onChangeSort" | "onChangePage" | "topRef">
|
||||
|
||||
@@ -1,13 +1,7 @@
|
||||
import { formatDistanceToNow } from "date-fns";
|
||||
import * as React from "react";
|
||||
|
||||
const LocaleTime = React.lazy(
|
||||
() =>
|
||||
import(
|
||||
/* webpackChunkName: "locale-time" */
|
||||
"~/components/LocaleTime"
|
||||
)
|
||||
);
|
||||
const LocaleTime = React.lazy(() => import("~/components/LocaleTime"));
|
||||
|
||||
type Props = React.ComponentProps<typeof LocaleTime> & {
|
||||
onClick?: () => void;
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
import "vite/modulepreload-polyfill";
|
||||
import "focus-visible";
|
||||
import "setimmediate";
|
||||
import { LazyMotion } from "framer-motion";
|
||||
import { KBarProvider } from "kbar";
|
||||
import { Provider } from "mobx-react";
|
||||
@@ -35,33 +38,6 @@ if (env.SENTRY_DSN) {
|
||||
initSentry(history);
|
||||
}
|
||||
|
||||
if ("serviceWorker" in window.navigator) {
|
||||
window.addEventListener("load", () => {
|
||||
// see: https://bugs.chromium.org/p/chromium/issues/detail?id=1097616
|
||||
// In some rare (<0.1% of cases) this call can return `undefined`
|
||||
const maybePromise = window.navigator.serviceWorker.register(
|
||||
"/static/service-worker.js",
|
||||
{
|
||||
scope: "/",
|
||||
}
|
||||
);
|
||||
|
||||
if (maybePromise?.then) {
|
||||
maybePromise
|
||||
.then((registration) => {
|
||||
Logger.debug("lifecycle", "SW registered: ", registration);
|
||||
})
|
||||
.catch((registrationError) => {
|
||||
Logger.debug(
|
||||
"lifecycle",
|
||||
"SW registration failed: ",
|
||||
registrationError
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Make sure to return the specific export containing the feature bundle.
|
||||
const loadFeatures = () => import("./utils/motion").then((res) => res.default);
|
||||
|
||||
@@ -116,13 +92,38 @@ window.addEventListener("load", async () => {
|
||||
return;
|
||||
}
|
||||
// https://github.com/googleanalytics/autotrack/issues/137#issuecomment-305890099
|
||||
await import(
|
||||
/* webpackChunkName: "autotrack" */
|
||||
"autotrack/autotrack.js"
|
||||
);
|
||||
await import("autotrack/autotrack.js");
|
||||
window.ga("require", "outboundLinkTracker");
|
||||
window.ga("require", "urlChangeTracker");
|
||||
window.ga("require", "eventTracker", {
|
||||
attributePrefix: "data-",
|
||||
});
|
||||
});
|
||||
|
||||
if ("serviceWorker" in navigator) {
|
||||
window.addEventListener("load", () => {
|
||||
// see: https://bugs.chromium.org/p/chromium/issues/detail?id=1097616
|
||||
// In some rare (<0.1% of cases) this call can return `undefined`
|
||||
const maybePromise = navigator.serviceWorker.register("/static/sw.js", {
|
||||
scope: "/",
|
||||
});
|
||||
|
||||
if (maybePromise?.then) {
|
||||
maybePromise
|
||||
.then((registration) => {
|
||||
Logger.debug(
|
||||
"lifecycle",
|
||||
"[ServiceWorker] Registered.",
|
||||
registration
|
||||
);
|
||||
})
|
||||
.catch((registrationError) => {
|
||||
Logger.debug(
|
||||
"lifecycle",
|
||||
"[ServiceWorker] Registration failed.",
|
||||
registrationError
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
NavigationNode,
|
||||
} from "@shared/types";
|
||||
import { sortNavigationNodes } from "@shared/utils/collections";
|
||||
import CollectionsStore from "~/stores/CollectionsStore";
|
||||
import type CollectionsStore from "~/stores/CollectionsStore";
|
||||
import Document from "~/models/Document";
|
||||
import ParanoidModel from "~/models/ParanoidModel";
|
||||
import { client } from "~/utils/ApiClient";
|
||||
@@ -18,9 +18,6 @@ export default class Collection extends ParanoidModel {
|
||||
@observable
|
||||
isSaving: boolean;
|
||||
|
||||
@observable
|
||||
isLoadingUsers: boolean;
|
||||
|
||||
@Field
|
||||
@observable
|
||||
id: string;
|
||||
|
||||
@@ -16,41 +16,11 @@ import useCurrentTeam from "~/hooks/useCurrentTeam";
|
||||
import usePolicy from "~/hooks/usePolicy";
|
||||
import { matchDocumentSlug as slug } from "~/utils/routeHelpers";
|
||||
|
||||
const SettingsRoutes = React.lazy(
|
||||
() =>
|
||||
import(
|
||||
/* webpackChunkName: "settings" */
|
||||
"./settings"
|
||||
)
|
||||
);
|
||||
const Document = React.lazy(
|
||||
() =>
|
||||
import(
|
||||
/* webpackChunkName: "preload-document" */
|
||||
"~/scenes/Document"
|
||||
)
|
||||
);
|
||||
const Collection = React.lazy(
|
||||
() =>
|
||||
import(
|
||||
/* webpackChunkName: "collection" */
|
||||
"~/scenes/Collection"
|
||||
)
|
||||
);
|
||||
const Home = React.lazy(
|
||||
() =>
|
||||
import(
|
||||
/* webpackChunkName: "home" */
|
||||
"~/scenes/Home"
|
||||
)
|
||||
);
|
||||
const Search = React.lazy(
|
||||
() =>
|
||||
import(
|
||||
/* webpackChunkName: "search" */
|
||||
"~/scenes/Search"
|
||||
)
|
||||
);
|
||||
const SettingsRoutes = React.lazy(() => import("./settings"));
|
||||
const Document = React.lazy(() => import("~/scenes/Document"));
|
||||
const Collection = React.lazy(() => import("~/scenes/Collection"));
|
||||
const Home = React.lazy(() => import("~/scenes/Home"));
|
||||
const Search = React.lazy(() => import("~/scenes/Search"));
|
||||
|
||||
const RedirectDocument = ({
|
||||
match,
|
||||
|
||||
@@ -6,41 +6,11 @@ import FullscreenLoading from "~/components/FullscreenLoading";
|
||||
import Route from "~/components/ProfiledRoute";
|
||||
import { matchDocumentSlug as slug } from "~/utils/routeHelpers";
|
||||
|
||||
const Authenticated = React.lazy(
|
||||
() =>
|
||||
import(
|
||||
/* webpackChunkName: "preload-authenticated" */
|
||||
"~/components/Authenticated"
|
||||
)
|
||||
);
|
||||
const AuthenticatedRoutes = React.lazy(
|
||||
() =>
|
||||
import(
|
||||
/* webpackChunkName: "preload-authenticated-routes" */
|
||||
"./authenticated"
|
||||
)
|
||||
);
|
||||
const SharedDocument = React.lazy(
|
||||
() =>
|
||||
import(
|
||||
/* webpackChunkName: "shared-document" */
|
||||
"~/scenes/Document/Shared"
|
||||
)
|
||||
);
|
||||
const Login = React.lazy(
|
||||
() =>
|
||||
import(
|
||||
/* webpackChunkName: "login" */
|
||||
"~/scenes/Login"
|
||||
)
|
||||
);
|
||||
const Logout = React.lazy(
|
||||
() =>
|
||||
import(
|
||||
/* webpackChunkName: "logout" */
|
||||
"~/scenes/Logout"
|
||||
)
|
||||
);
|
||||
const Authenticated = React.lazy(() => import("~/components/Authenticated"));
|
||||
const AuthenticatedRoutes = React.lazy(() => import("./authenticated"));
|
||||
const SharedDocument = React.lazy(() => import("~/scenes/Document/Shared"));
|
||||
const Login = React.lazy(() => import("~/scenes/Login"));
|
||||
const Logout = React.lazy(() => import("~/scenes/Logout"));
|
||||
|
||||
export default function Routes() {
|
||||
return (
|
||||
|
||||
@@ -1,11 +1,5 @@
|
||||
import * as React from "react";
|
||||
|
||||
const MultiplayerEditor = React.lazy(
|
||||
() =>
|
||||
import(
|
||||
/* webpackChunkName: "preload-multiplayer-editor" */
|
||||
"./MultiplayerEditor"
|
||||
)
|
||||
);
|
||||
const MultiplayerEditor = React.lazy(() => import("./MultiplayerEditor"));
|
||||
|
||||
export default MultiplayerEditor;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import invariant from "invariant";
|
||||
import { orderBy } from "lodash";
|
||||
import { lowerFirst, orderBy } from "lodash";
|
||||
import { observable, action, computed, runInAction } from "mobx";
|
||||
import { Class } from "utility-types";
|
||||
import RootStore from "~/stores/RootStore";
|
||||
@@ -20,10 +20,6 @@ export enum RPCAction {
|
||||
|
||||
type FetchPageParams = PaginationParams & Record<string, any>;
|
||||
|
||||
function modelNameFromClassName(string: string) {
|
||||
return string.charAt(0).toLowerCase() + string.slice(1);
|
||||
}
|
||||
|
||||
export const DEFAULT_PAGINATION_LIMIT = 25;
|
||||
|
||||
export const PAGINATION_SYMBOL = Symbol.for("pagination");
|
||||
@@ -61,7 +57,7 @@ export default abstract class BaseStore<T extends BaseModel> {
|
||||
constructor(rootStore: RootStore, model: Class<T>) {
|
||||
this.rootStore = rootStore;
|
||||
this.model = model;
|
||||
this.modelName = modelNameFromClassName(model.name);
|
||||
this.modelName = lowerFirst(model.name);
|
||||
|
||||
if (!this.apiEndpoint) {
|
||||
this.apiEndpoint = `${this.modelName}s`;
|
||||
|
||||
12
app/typings/window.d.ts
vendored
12
app/typings/window.d.ts
vendored
@@ -1,11 +1,9 @@
|
||||
declare global {
|
||||
interface NodeRequire {
|
||||
/** A special feature supported by webpack's compiler that allows you to get all matching modules starting from some base directory. */
|
||||
context: (
|
||||
directory: string,
|
||||
useSubdirectories: boolean,
|
||||
regExp: RegExp
|
||||
) => any;
|
||||
interface ImportMeta {
|
||||
/**
|
||||
* A special feature that allows you to get all matching modules starting from some base directory.
|
||||
*/
|
||||
glob: (pattern: string, option?: { eager: boolean }) => any;
|
||||
}
|
||||
|
||||
interface Window {
|
||||
|
||||
@@ -13,25 +13,31 @@ export function loadPlugins(): { [id: string]: Plugin } {
|
||||
const plugins = {};
|
||||
|
||||
function importAll(r: any, property: string) {
|
||||
r.keys().forEach((key: string) => {
|
||||
const id = key.split("/")[1];
|
||||
Object.keys(r).forEach((key: string) => {
|
||||
const id = key.split("/")[3];
|
||||
plugins[id] = plugins[id] || {
|
||||
id,
|
||||
};
|
||||
|
||||
const plugin = r(key);
|
||||
plugins[id][property] = "default" in plugin ? plugin.default : plugin;
|
||||
plugins[id][property] = r[key].default;
|
||||
});
|
||||
}
|
||||
|
||||
importAll(
|
||||
require.context("../../plugins", true, /client\/Settings\.[tj]sx?$/),
|
||||
import.meta.glob("../../plugins/*/client/Settings.{ts,js,tsx,jsx}", {
|
||||
eager: true,
|
||||
}),
|
||||
"settings"
|
||||
);
|
||||
importAll(
|
||||
require.context("../../plugins", true, /client\/Icon\.[tj]sx?$/),
|
||||
import.meta.glob("../../plugins/*/client/Icon.{ts,js,tsx,jsx}", {
|
||||
eager: true,
|
||||
}),
|
||||
"icon"
|
||||
);
|
||||
importAll(require.context("../../plugins", true, /plugin\.json?$/), "config");
|
||||
importAll(
|
||||
import.meta.glob("../../plugins/*/plugin.json", { eager: true }),
|
||||
"config"
|
||||
);
|
||||
|
||||
return plugins;
|
||||
}
|
||||
|
||||
@@ -8,10 +8,7 @@ export async function loadPolyfills() {
|
||||
|
||||
if (!supportsResizeObserver()) {
|
||||
polyfills.push(
|
||||
import(
|
||||
/* webpackChunkName: "resize-observer" */
|
||||
"@juggle/resize-observer"
|
||||
).then((module) => {
|
||||
import("@juggle/resize-observer").then((module) => {
|
||||
window.ResizeObserver = module.ResizeObserver;
|
||||
})
|
||||
);
|
||||
@@ -27,8 +24,8 @@ export async function loadPolyfills() {
|
||||
*/
|
||||
function supportsResizeObserver() {
|
||||
return (
|
||||
"ResizeObserver" in global &&
|
||||
"ResizeObserverEntry" in global &&
|
||||
"ResizeObserver" in window &&
|
||||
"ResizeObserverEntry" in window &&
|
||||
"contentRect" in ResizeObserverEntry.prototype
|
||||
);
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ export function initSentry(history: History) {
|
||||
],
|
||||
tracesSampleRate: env.ENVIRONMENT === "production" ? 0.1 : 1,
|
||||
ignoreErrors: [
|
||||
"Failed to fetch dynamically imported module",
|
||||
"ResizeObserver loop completed with undelivered notifications",
|
||||
"ResizeObserver loop limit exceeded",
|
||||
"AuthorizationError",
|
||||
@@ -26,8 +27,8 @@ export function initSentry(history: History) {
|
||||
"RateLimitExceededError",
|
||||
"ServiceUnavailableError",
|
||||
"UpdateRequiredError",
|
||||
"ChunkLoadError",
|
||||
"file://",
|
||||
"chrome-extension://",
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user