diff --git a/.changeset/enable-css-features-by-default.md b/.changeset/enable-css-features-by-default.md new file mode 100644 index 00000000000..fa7f23b3e84 --- /dev/null +++ b/.changeset/enable-css-features-by-default.md @@ -0,0 +1,16 @@ +--- +"@remix-run/dev": major +--- + +Enable built-in PostCSS and Tailwind support by default. + +These tools are now automatically used within the Remix compiler if PostCSS and/or Tailwind configuration files are present in your project. + +If you have a custom PostCSS and/or Tailwind setup outside of Remix, you can disable these features in your `remix.config.js`. + +```js +module.exports = { + postcss: false, + tailwind: false, +}; +``` diff --git a/docs/file-conventions/remix-config.md b/docs/file-conventions/remix-config.md index 80f6fd13bbd..93aa016aac7 100644 --- a/docs/file-conventions/remix-config.md +++ b/docs/file-conventions/remix-config.md @@ -72,7 +72,7 @@ The URL prefix of the browser build with a trailing slash. Defaults to ## postcss -Whether to process CSS using [PostCSS][postcss] if `postcss.config.js` is present. Defaults to `false`. +Whether to process CSS using [PostCSS][postcss] if `postcss.config.js` is present. Defaults to `true`. ## routes @@ -249,7 +249,7 @@ The platform the server build is targeting, which can either be `"neutral"` or ## tailwind -Whether to support [Tailwind functions and directives][tailwind-functions-and-directives] in CSS files if `tailwindcss` is installed. Defaults to `false`. +Whether to support [Tailwind functions and directives][tailwind-functions-and-directives] in CSS files if `tailwindcss` is installed. Defaults to `true`. ## watchPaths diff --git a/docs/guides/migrating-react-router-app.md b/docs/guides/migrating-react-router-app.md index 033adcd806c..13d2d72aeb8 100644 --- a/docs/guides/migrating-react-router-app.md +++ b/docs/guides/migrating-react-router-app.md @@ -615,18 +615,6 @@ You'll notice on line 32 that we've rendered a `` component that replac If you currently inject `` tags into your page client-side in your existing route components, either directly or via an abstraction like [`react-helmet`][react-helmet], you can stop doing that and instead use the `links` export. You get to delete a lot of code and possibly a dependency or two! -### PostCSS - -To enable [PostCSS] support, set the `postcss` option to `true` in `remix.config.js`. Remix will then automatically process your styles with PostCSS if a `postcss.config.js` file is present. - -```js filename=remix.config.js -/** @type {import('@remix-run/dev').AppConfig} */ -module.exports = { - postcss: true, - // ... -}; -``` - ### CSS bundling Remix has built-in support for [CSS Modules][css-modules], [Vanilla Extract][vanilla-extract] and [CSS side effect imports][css-side-effect-imports]. In order to make use of these features, you'll need to set up CSS bundling in your application. @@ -757,7 +745,6 @@ Now then, go off and _remix your app_. We think you'll like what you build along [styling-in-remix]: ./styling [frequently-asked-questions]: ../pages/faq [common-gotchas]: ../pages/gotchas -[postcss]: ./styling#postcss [css-modules]: ./styling#css-modules [vanilla-extract]: ./styling#vanilla-extract [css-side-effect-imports]: ./styling#css-side-effect-imports diff --git a/docs/guides/styling.md b/docs/guides/styling.md index 0b037f2aea5..cf1dd70ddfa 100644 --- a/docs/guides/styling.md +++ b/docs/guides/styling.md @@ -404,17 +404,7 @@ export const links: LinksFunction = () => { Perhaps the most popular way to style a Remix application in the community is to use [Tailwind CSS][tailwind]. It has the benefits of inline-style collocation for developer ergonomics and is able to generate a CSS file for Remix to import. The generated CSS file generally caps out around 8-10kb, even for large applications. Load that file into the `root.tsx` links and be done with it. If you don't have any CSS opinions, this is a great approach. -To use the built-in Tailwind support, first enable the `tailwind` option in `remix.config.js`: - -```js filename=remix.config.js -/** @type {import('@remix-run/dev').AppConfig} */ -module.exports = { - tailwind: true, - // ... -}; -``` - -Install Tailwind as a dev dependency: +To use Tailwind, first install it as a dev dependency: ```sh npm install -D tailwindcss @@ -470,6 +460,8 @@ If you're using VS Code, it's recommended you install the [Tailwind IntelliSense It's recommended that you avoid Tailwind's `@import` syntax (e.g. `@import 'tailwindcss/base'`) in favor of Tailwind directives (e.g. `@tailwind base`). Tailwind replaces its import statements with inlined CSS but this can result in the interleaving of styles and import statements. This clashes with the restriction that all import statements must be at the start of the file. Alternatively, you can use [PostCSS][built-in-post-css-support] with the [postcss-import] plugin to process imports before passing them to esbuild. +Built-in Tailwind support can be disabled by setting the `tailwind` option to `false` in `remix.config.js`. + ## Remote Stylesheets You can load stylesheets from any server, here's an example of loading a modern css reset from unpkg. @@ -491,17 +483,7 @@ export const links: LinksFunction = () => { [PostCSS][postcss] is a popular tool with a rich plugin ecosystem, commonly used to prefix CSS for older browsers, transpile future CSS syntax, inline images, lint your styles and more. When a PostCSS config is detected, Remix will automatically run PostCSS across all CSS in your project. -For example, to use [Autoprefixer][autoprefixer], first enable the `postcss` option in `remix.config.js`: - -```js filename=remix.config.js -/** @type {import('@remix-run/dev').AppConfig} */ -module.exports = { - postcss: true, - // ... -}; -``` - -Install the PostCSS plugin. +For example, to use [Autoprefixer][autoprefixer], first install the PostCSS plugin. ```sh npm install -D autoprefixer @@ -531,6 +513,8 @@ module.exports = (ctx) => { }; ``` +Built-in PostCSS support can be disabled by setting the `postcss` option to `false` in `remix.config.js`. + ## CSS Preprocessors You can use CSS preprocessors like LESS and SASS. Doing so requires running an additional build process to convert these files to CSS files. This can be done via the command line tools provided by the preprocessor or any equivalent tool. diff --git a/integration/deterministic-build-output-test.ts b/integration/deterministic-build-output-test.ts index 458035340fc..c8c107d06ed 100644 --- a/integration/deterministic-build-output-test.ts +++ b/integration/deterministic-build-output-test.ts @@ -27,7 +27,6 @@ test("builds deterministically under different paths", async () => { // * vanillaExtractPlugin (via app/routes/foo.tsx' .css.ts file import) let init: FixtureInit = { config: { - postcss: true, future: { v2_routeConvention: true, }, diff --git a/integration/hmr-log-test.ts b/integration/hmr-log-test.ts index 4dc69a71426..1691476cf5d 100644 --- a/integration/hmr-log-test.ts +++ b/integration/hmr-log-test.ts @@ -13,7 +13,6 @@ test.setTimeout(120_000); let fixture = (options: { appPort: number; devPort: number }): FixtureInit => ({ config: { serverModuleFormat: "cjs", - tailwind: true, future: { v2_dev: { port: options.devPort, diff --git a/integration/hmr-test.ts b/integration/hmr-test.ts index 476040777ba..8df8a747317 100644 --- a/integration/hmr-test.ts +++ b/integration/hmr-test.ts @@ -13,7 +13,6 @@ test.setTimeout(150_000); let fixture = (options: { appPort: number; devPort: number }): FixtureInit => ({ config: { serverModuleFormat: "cjs", - postcss: true, future: { v2_dev: { port: options.devPort, diff --git a/integration/postcss-test.ts b/integration/postcss-test.ts index c78c7bf9946..2d689632e08 100644 --- a/integration/postcss-test.ts +++ b/integration/postcss-test.ts @@ -34,8 +34,6 @@ test.describe("PostCSS enabled", () => { test.beforeAll(async () => { fixture = await createFixture({ config: { - postcss: true, - tailwind: true, future: { v2_routeConvention: true, }, @@ -350,92 +348,6 @@ test.describe("PostCSS enabled", () => { }); }); -test.describe("PostCSS enabled via unstable future flag", () => { - let fixture: Fixture; - let appFixture: AppFixture; - - test.beforeAll(async () => { - fixture = await createFixture({ - config: { - future: { - unstable_postcss: true, - }, - }, - files: { - "postcss.config.js": js` - module.exports = (ctx) => ({ - plugins: [ - { - postcssPlugin: 'replace', - Declaration (decl) { - decl.value = decl.value - .replace( - /TEST_PADDING_VALUE/g, - ${JSON.stringify(TEST_PADDING_VALUE)}, - ); - }, - }, - ], - }); - `, - "app/root.jsx": js` - import { Links, Outlet } from "@remix-run/react"; - export default function Root() { - return ( - - - - - - - - - ) - } - `, - "app/routes/postcss-unstable-future-flag-test.jsx": js` - import { Test, links as testLinks } from "~/test-components/postcss-unstable-future-flag"; - export function links() { - return [...testLinks()]; - } - export default function() { - return ; - } - `, - "app/test-components/postcss-unstable-future-flag/index.jsx": js` - import stylesHref from "./styles.css"; - export function links() { - return [{ rel: 'stylesheet', href: stylesHref }]; - } - export function Test() { - return ( -
-

PostCSS unstable future flag test.

-
- ); - } - `, - "app/test-components/postcss-unstable-future-flag/styles.css": css` - .postcss-unstable-future-flag-test { - padding: TEST_PADDING_VALUE; - } - `, - }, - }); - appFixture = await createAppFixture(fixture); - }); - - test.afterAll(() => appFixture.close()); - - test("uses PostCSS config", async ({ page }) => { - let app = new PlaywrightFixture(appFixture, page); - await app.goto("/postcss-unstable-future-flag-test"); - let locator = await page.getByTestId("postcss-unstable-future-flag"); - let padding = await locator.evaluate((el) => getComputedStyle(el).padding); - expect(padding).toBe(TEST_PADDING_VALUE); - }); -}); - test.describe("PostCSS disabled", () => { let fixture: Fixture; let appFixture: AppFixture; diff --git a/integration/tailwind-test.ts b/integration/tailwind-test.ts index cda2f2ad845..d1673972089 100644 --- a/integration/tailwind-test.ts +++ b/integration/tailwind-test.ts @@ -44,7 +44,6 @@ function runTests(ext: typeof extensions[number]) { test.beforeAll(async () => { fixture = await createFixture({ config: { - tailwind: true, future: { v2_routeConvention: true, }, @@ -329,83 +328,6 @@ test.describe("Tailwind enabled", () => { } }); -test.describe("Tailwind enabled via unstable future flag", () => { - let fixture: Fixture; - let appFixture: AppFixture; - - test.beforeAll(async () => { - fixture = await createFixture({ - config: { - future: { - unstable_tailwind: true, - }, - }, - files: { - "tailwind.config.js": js` - module.exports = { - content: ["./app/**/*.{ts,tsx,jsx,js}"], - theme: { - spacing: { - 'test': ${JSON.stringify(TEST_PADDING_VALUE)} - }, - }, - } - `, - "app/tailwind.css": css` - @tailwind base; - @tailwind components; - @tailwind utilities; - `, - "app/root.jsx": js` - import { Links, Outlet } from "@remix-run/react"; - import { cssBundleHref } from "@remix-run/css-bundle"; - import tailwindHref from "./tailwind.css" - export function links() { - return [ - { rel: "stylesheet", href: tailwindHref }, - { rel: "stylesheet", href: cssBundleHref } - ]; - } - export default function Root() { - return ( - - - - - - - - - ) - } - `, - "app/routes/unstable-future-flag-test.jsx": js` - export default function() { - return ( -
- Unstable future flag test -
- ); - } - `, - }, - }); - appFixture = await createAppFixture(fixture); - }); - - test.afterAll(() => appFixture.close()); - - test("uses Tailwind config", async ({ page }) => { - let app = new PlaywrightFixture(appFixture, page); - await app.goto("/unstable-future-flag-test"); - let locator = page.getByTestId("unstable-future-flag"); - let padding = await locator.evaluate( - (element) => window.getComputedStyle(element).padding - ); - expect(padding).toBe(TEST_PADDING_VALUE); - }); -}); - test.describe("Tailwind disabled", () => { let fixture: Fixture; let appFixture: AppFixture; diff --git a/packages/remix-dev/__tests__/readConfig-test.ts b/packages/remix-dev/__tests__/readConfig-test.ts index 580b2db0ad2..da6bbd772be 100644 --- a/packages/remix-dev/__tests__/readConfig-test.ts +++ b/packages/remix-dev/__tests__/readConfig-test.ts @@ -25,8 +25,6 @@ describe("readConfig", () => { entryServerFilePath: expect.any(String), tsconfigPath: expect.any(String), future: { - unstable_postcss: expect.any(Boolean), - unstable_tailwind: expect.any(Boolean), v2_headers: expect.any(Boolean), v2_meta: expect.any(Boolean), v2_routeConvention: expect.any(Boolean), @@ -44,15 +42,13 @@ describe("readConfig", () => { "entryServerFile": "entry.server.tsx", "entryServerFilePath": Any, "future": Object { - "unstable_postcss": Any, - "unstable_tailwind": Any, "v2_dev": false, "v2_headers": Any, "v2_meta": Any, "v2_routeConvention": Any, }, "mdx": undefined, - "postcss": false, + "postcss": true, "publicPath": "/build/", "relativeAssetsBuildDirectory": Any, "rootDirectory": Any, @@ -77,7 +73,7 @@ describe("readConfig", () => { "serverModuleFormat": "cjs", "serverNodeBuiltinsPolyfill": undefined, "serverPlatform": "node", - "tailwind": false, + "tailwind": true, "tsconfigPath": Any, "watchPaths": Array [], } diff --git a/packages/remix-dev/config.ts b/packages/remix-dev/config.ts index 0d9ad9c06d7..4c4c34cc125 100644 --- a/packages/remix-dev/config.ts +++ b/packages/remix-dev/config.ts @@ -45,10 +45,6 @@ type Dev = { interface FutureConfig { v2_dev: boolean | Dev; - /** @deprecated Use the `postcss` config option instead */ - unstable_postcss: boolean; - /** @deprecated Use the `tailwind` config option instead */ - unstable_tailwind: boolean; v2_headers: boolean; v2_meta: boolean; v2_routeConvention: boolean; @@ -114,7 +110,7 @@ export interface AppConfig { /** * Whether to process CSS using PostCSS if `postcss.config.js` is present. - * Defaults to `false`. + * Defaults to `true`. */ postcss?: boolean; @@ -179,7 +175,7 @@ export interface AppConfig { /** * Whether to support Tailwind functions and directives in CSS files if `tailwindcss` is installed. - * Defaults to `false`. + * Defaults to `true`. */ tailwind?: boolean; @@ -277,7 +273,7 @@ export interface RemixConfig { /** * Whether to process CSS using PostCSS if `postcss.config.js` is present. - * Defaults to `false`. + * Defaults to `true`. */ postcss: boolean; @@ -350,7 +346,7 @@ export interface RemixConfig { /** * Whether to support Tailwind functions and directives in CSS files if `tailwindcss` is installed. - * Defaults to `false`. + * Defaults to `true`. */ tailwind: boolean; @@ -510,32 +506,6 @@ export async function readConfig( } if (appConfig.future) { - if (appConfig.future.unstable_postcss !== undefined) { - logger.warn( - "The `future.unstable_postcss` config option has been deprecated.", - { - details: [ - "PostCSS support is now stable.", - "Use the `postcss` config option instead.", - ], - key: "unstable_postcss", - } - ); - } - - if (appConfig.future.unstable_tailwind !== undefined) { - logger.warn( - "The `future.unstable_tailwind` config option has been deprecated.", - { - details: [ - "Tailwind support is now stable.", - "Use the `tailwind` config option instead.", - ], - key: "unstable_tailwind", - } - ); - } - if ("unstable_dev" in appConfig.future) { logger.warn("The `future.unstable_dev` config option has been removed", { details: [ @@ -549,10 +519,8 @@ export async function readConfig( } let mdx = appConfig.mdx; - let postcss = - appConfig.postcss ?? appConfig.future?.unstable_postcss === true; - let tailwind = - appConfig.tailwind ?? appConfig.future?.unstable_tailwind === true; + let postcss = appConfig.postcss ?? true; + let tailwind = appConfig.tailwind ?? true; let appDirectory = path.resolve( rootDirectory, @@ -760,8 +728,6 @@ export async function readConfig( let future: FutureConfig = { v2_dev: appConfig.future?.v2_dev ?? false, - unstable_postcss: appConfig.future?.unstable_postcss === true, - unstable_tailwind: appConfig.future?.unstable_tailwind === true, v2_headers: appConfig.future?.v2_headers === true, v2_meta: appConfig.future?.v2_meta === true, v2_routeConvention: appConfig.future?.v2_routeConvention === true, diff --git a/packages/remix-react/entry.ts b/packages/remix-react/entry.ts index bfb537a3c9d..d1513a7f6b3 100644 --- a/packages/remix-react/entry.ts +++ b/packages/remix-react/entry.ts @@ -34,10 +34,6 @@ type Dev = { export interface FutureConfig { v2_dev: boolean | Dev; - /** @deprecated Use the `postcss` config option instead */ - unstable_postcss: boolean; - /** @deprecated Use the `tailwind` config option instead */ - unstable_tailwind: boolean; v2_headers: boolean; v2_meta: boolean; v2_routeConvention: boolean; diff --git a/packages/remix-server-runtime/entry.ts b/packages/remix-server-runtime/entry.ts index ca72bce0102..eba9031e093 100644 --- a/packages/remix-server-runtime/entry.ts +++ b/packages/remix-server-runtime/entry.ts @@ -22,10 +22,6 @@ type Dev = { export interface FutureConfig { v2_dev: boolean | Dev; - /** @deprecated Use the `postcss` config option instead */ - unstable_postcss: boolean; - /** @deprecated Use the `tailwind` config option instead */ - unstable_tailwind: boolean; v2_headers: boolean; v2_meta: boolean; v2_routeConvention: boolean; diff --git a/packages/remix-testing/create-remix-stub.tsx b/packages/remix-testing/create-remix-stub.tsx index caa07c7bc83..27cbd7fa6a8 100644 --- a/packages/remix-testing/create-remix-stub.tsx +++ b/packages/remix-testing/create-remix-stub.tsx @@ -125,8 +125,6 @@ export function createRemixStub( remixContextRef.current = { future: { v2_dev: false, - unstable_postcss: false, - unstable_tailwind: false, v2_headers: false, v2_meta: false, v2_routeConvention: false, diff --git a/scripts/playground/template/remix.config.js b/scripts/playground/template/remix.config.js index 4cf3e14cb57..d88ac009675 100644 --- a/scripts/playground/template/remix.config.js +++ b/scripts/playground/template/remix.config.js @@ -2,7 +2,6 @@ module.exports = { cacheDirectory: "./node_modules/.cache/remix", ignoredRouteFiles: ["**/.*", "**/*.css", "**/*.test.{js,jsx,ts,tsx}"], - tailwind: true, future: { v2_meta: true, },