Skip to content

Commit

Permalink
Replace Webpack with Vite (outline#4765)
Browse files Browse the repository at this point in the history
Co-authored-by: Tom Moor <tom@getoutline.com>
Co-authored-by: Vio <vio@beanon.com>
  • Loading branch information
3 people committed Feb 16, 2023
1 parent 490d05b commit e754f89
Show file tree
Hide file tree
Showing 40 changed files with 1,689 additions and 3,608 deletions.
7 changes: 5 additions & 2 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,11 @@ jobs:
- restore_cache:
key: dependency-cache-{{ checksum "package.json" }}
- run:
name: build-webpack
command: yarn build:webpack
name: build-vite
command: yarn vite:build
- run:
name: Send bundle stats to RelativeCI
command: npx relative-ci-agent
build-image:
executor: docker-publisher
steps:
Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ fakes3/*
.idea
*.pem
*.key
*.cert
*.cert
20 changes: 3 additions & 17 deletions app/components/AuthenticatedLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
2 changes: 1 addition & 1 deletion app/components/Collaborators.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down
8 changes: 1 addition & 7 deletions app/components/Editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
6 changes: 4 additions & 2 deletions app/components/ErrorBoundary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 (
Expand Down
6 changes: 1 addition & 5 deletions app/components/IconPicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand Down
8 changes: 1 addition & 7 deletions app/components/TableFromParams.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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">
Expand Down
8 changes: 1 addition & 7 deletions app/components/Time.tsx
Original file line number Diff line number Diff line change
@@ -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;
Expand Down
63 changes: 32 additions & 31 deletions app/index.tsx
Original file line number Diff line number Diff line change
@@ -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";
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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
);
});
}
});
}
5 changes: 1 addition & 4 deletions app/models/Collection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -18,9 +18,6 @@ export default class Collection extends ParanoidModel {
@observable
isSaving: boolean;

@observable
isLoadingUsers: boolean;

@Field
@observable
id: string;
Expand Down
40 changes: 5 additions & 35 deletions app/routes/authenticated.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
40 changes: 5 additions & 35 deletions app/routes/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand Down
8 changes: 1 addition & 7 deletions app/scenes/Document/components/AsyncMultiplayerEditor.ts
Original file line number Diff line number Diff line change
@@ -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;
8 changes: 2 additions & 6 deletions app/stores/BaseStore.ts
Original file line number Diff line number Diff line change
@@ -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";
Expand All @@ -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");
Expand Down Expand Up @@ -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`;
Expand Down
12 changes: 5 additions & 7 deletions app/typings/window.d.ts
Original file line number Diff line number Diff line change
@@ -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 {
Expand Down
Loading

0 comments on commit e754f89

Please sign in to comment.