Skip to content

Commit

Permalink
feat(tailwind): Smaller bundle size (#1383)
Browse files Browse the repository at this point in the history
Co-authored-by: Ben Read <endymion1818@gmail.com>
Co-authored-by: Benny Burrito <87976514+bennyburrito@users.noreply.github.com>
Co-authored-by: Ben Verspeak <ben.verspeak@yonderland.com>
Co-authored-by: hank <paperflood@qq.com>
Co-authored-by: zhanghong <hong.zhang@axinan.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Ben Gracewood <ben@gracewood.nz>
Co-authored-by: Victor Laforet <vlaforet@users.noreply.github.com>
Co-authored-by: Bu Kinoshita <6929565+bukinoshita@users.noreply.github.com>
Co-authored-by: Vitor Capretz <capretzvitor@gmail.com>
  • Loading branch information
11 people committed Oct 14, 2024
1 parent 7ba9b86 commit d8b4630
Show file tree
Hide file tree
Showing 78 changed files with 18,447 additions and 1,770 deletions.
5 changes: 5 additions & 0 deletions .changeset/quiet-donkeys-brush.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@react-email/tailwind": minor
---

Refactored internally to have a much smaller bundle size
4 changes: 0 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,6 @@
"overrides": {
"@types/react": "npm:types-react@19.0.0-rc.1",
"@types/react-dom": "npm:types-react-dom@19.0.0-rc.1"
},
"patchedDependencies": {
"process@0.11.10": "patches/process@0.11.10.patch",
"tailwindcss@3.3.2": "patches/tailwindcss@3.3.2.patch"
}
}
}
1 change: 1 addition & 0 deletions packages/tailwind/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/** @type {import('eslint').ESLint.ConfigData} */
module.exports = {
extends: ["custom/react-internal"],
ignorePatterns: ["integrations/**/*"],
plugins: [
/* just a plugin to create custom linting rules with regex */
"regex"
Expand Down
8 changes: 8 additions & 0 deletions packages/tailwind/integrations/_tests/nextjs.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import path from "node:path";
import { $ } from "./utils/run-testing-command";

test.sequential("Tailwind works on the Next App's build process", () => {
const nextAppLocation = path.resolve(__dirname, "../nextjs");
$("npm install", nextAppLocation);
$("npm run build", nextAppLocation);
});
17 changes: 17 additions & 0 deletions packages/tailwind/integrations/_tests/utils/run-testing-command.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import path from "path";
import shell from "shelljs";

/**
* Just a function that runs `shell.exec` and expects it returns code 0, i.e. expects command not to fail
*
* Defaults the CWD to the @react-email/tailwind project's directory
*/
export const $ = (
command: string,
cwd: string = path.resolve(__dirname, ".."),
) => {
expect(
shell.exec(command, { cwd, fatal: true }).code,
`Expected command "${command}" to work properly but it returned a non-zero exit code`,
).toBe(0);
};
8 changes: 8 additions & 0 deletions packages/tailwind/integrations/_tests/vite.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import path from "node:path";
import { $ } from "./utils/run-testing-command";

test.sequential("Tailwind works on the Vite App's build process", () => {
const viteAppLocation = path.resolve(__dirname, "../vite");
$("npm install", viteAppLocation);
$("npm run build", viteAppLocation);
});
39 changes: 39 additions & 0 deletions packages/tailwind/integrations/nextjs/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.yalc
yalc.lock
.pnp.js
yalc.lock
.yarn/install-state.gz

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# local env files
.env*.local

# vercel
.vercel

# typescript
*.tsbuildinfo
next-env.d.ts
9 changes: 9 additions & 0 deletions packages/tailwind/integrations/nextjs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
This is a NextJS project bootstrapped with `create-next-app@latest` that contains a Tailwind
email using most of the features we provide that will be auto-built on testing to
make sure this new release works properly with the latest version of NextJS when being built.

We do this testing so that things are more reliable and this couldn't be done using pnpm
workspaces as they link code instead of actually copying the content into node_modules.
The solution we use to copy the code in a way that mimics the actual `npm install @react-email/tailwind` is `yalc`.

Se [the test file](../_tests/nextjs.spec.ts) for more info.
152 changes: 152 additions & 0 deletions packages/tailwind/integrations/nextjs/emails/vercel-invite-user.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
import {
Body,
Button,
Container,
Column,
Head,
Heading,
Hr,
Html,
Img,
Link,
Preview,
Row,
Section,
Text,
} from "@react-email/components";
import { Tailwind } from "@react-email/tailwind";
import * as React from "react";

interface VercelInviteUserEmailProps {
username?: string;
userImage?: string;
invitedByUsername?: string;
invitedByEmail?: string;
teamName?: string;
teamImage?: string;
inviteLink?: string;
inviteFromIp?: string;
inviteFromLocation?: string;
}

const baseUrl = process.env.VERCEL_URL
? `https://${process.env.VERCEL_URL}`
: "";

export const VercelInviteUserEmail = ({
username,
userImage,
invitedByUsername,
invitedByEmail,
teamName,
teamImage,
inviteLink,
inviteFromIp,
inviteFromLocation,
}: VercelInviteUserEmailProps) => {
const previewText = `Join ${invitedByUsername} on Vercel`;

return (
<Html>
<Head />
<Preview>{previewText}</Preview>
<Tailwind>
<Body className="bg-white my-auto mx-auto font-sans px-2">
<Container className="border border-solid border-[#eaeaea] rounded my-[40px] mx-auto p-[20px] max-w-[465px]">
<Section className="mt-[32px]">
<Img
src={`${baseUrl}/static/vercel-logo.png`}
width="40"
height="37"
alt="Vercel"
className="my-0 mx-auto"
/>
</Section>
<Heading className="text-black text-[24px] font-normal text-center p-0 my-[30px] mx-0">
Join <strong>{teamName}</strong> on <strong>Vercel</strong>
</Heading>
<Text className="text-black text-[14px] leading-[24px]">
Hello {username},
</Text>
<Text className="text-black text-[14px] leading-[24px]">
<strong>{invitedByUsername}</strong> (
<Link
href={`mailto:${invitedByEmail}`}
className="text-blue-600 no-underline"
>
{invitedByEmail}
</Link>
) has invited you to the <strong>{teamName}</strong> team on{" "}
<strong>Vercel</strong>.
</Text>
<Section>
<Row>
<Column align="right">
<Img
className="rounded-full"
src={userImage}
width="64"
height="64"
/>
</Column>
<Column align="center">
<Img
src={`${baseUrl}/static/vercel-arrow.png`}
width="12"
height="9"
alt="invited you to"
/>
</Column>
<Column align="left">
<Img
className="rounded-full"
src={teamImage}
width="64"
height="64"
/>
</Column>
</Row>
</Section>
<Section className="text-center mt-[32px] mb-[32px]">
<Button
className="bg-[#000000] rounded text-white text-[12px] font-semibold no-underline text-center px-5 py-3"
href={inviteLink}
>
Join the team
</Button>
</Section>
<Text className="text-black text-[14px] leading-[24px]">
or copy and paste this URL into your browser:{" "}
<Link href={inviteLink} className="text-blue-600 no-underline">
{inviteLink}
</Link>
</Text>
<Hr className="border border-solid border-[#eaeaea] my-[26px] mx-0 w-full" />
<Text className="text-[#666666] text-[12px] leading-[24px]">
This invitation was intended for{" "}
<span className="text-black">{username}</span>. This invite was
sent from <span className="text-black">{inviteFromIp}</span>{" "}
located in{" "}
<span className="text-black">{inviteFromLocation}</span>. If you
were not expecting this invitation, you can ignore this email. If
you are concerned about your account's safety, please reply to
this email to get in touch with us.
</Text>
</Container>
</Body>
</Tailwind>
</Html>
);
};

VercelInviteUserEmail.PreviewProps = {
username: "alanturing",
userImage: `${baseUrl}/static/vercel-user.png`,
invitedByUsername: "Alan",
invitedByEmail: "alan.turing@example.com",
teamName: "Enigma",
teamImage: `${baseUrl}/static/vercel-team.png`,
inviteLink: "https://vercel.com/teams/invite/foo",
inviteFromIp: "204.13.186.218",
inviteFromLocation: "São Paulo, Brazil",
} as VercelInviteUserEmailProps;
5 changes: 5 additions & 0 deletions packages/tailwind/integrations/nextjs/next-env.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />

// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.
7 changes: 7 additions & 0 deletions packages/tailwind/integrations/nextjs/next.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
compress: false,
swcMinify: false,
};

export default nextConfig;
Loading

0 comments on commit d8b4630

Please sign in to comment.