Skip to content

Commit

Permalink
Support CSS options in Vite projects (#2245)
Browse files Browse the repository at this point in the history
* Remove tailwind v3 from example

* Restore styling flag

* Deprecate css-modules and postcss strategies

* Make commands work only for Vite

* Use tailwind v4 for Vite

* Support vanilla-extract in Vite

* Multiple fixes

* More fixes

* Changesets

* Fix tests

* Fix prettier

* Update snapshot test

* Minor perf

* Update Tailwind version

* Changesets

* Add warning for npm and tailwind
  • Loading branch information
frandiox authored Jul 8, 2024
1 parent 0f91388 commit c269065
Show file tree
Hide file tree
Showing 27 changed files with 460 additions and 452 deletions.
5 changes: 5 additions & 0 deletions .changeset/rare-bags-attack.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@shopify/cli-hydrogen': minor
---

Support Vite projects in `h2 setup css` command to setup Tailwind and vanilla-extract. Drop CSS setup support for classic Remix projects.
2 changes: 1 addition & 1 deletion docs/preview/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"devDependencies": {
"@remix-run/dev": "^2.10.1",
"@remix-run/eslint-config": "^2.10.1",
"@tailwindcss/vite": "4.0.0-alpha.16",
"@tailwindcss/vite": "4.0.0-alpha.17",
"@types/he": "^1.2.1",
"@types/react": "^18.2.20",
"@types/react-dom": "^18.2.7",
Expand Down
369 changes: 204 additions & 165 deletions package-lock.json

Large diffs are not rendered by default.

6 changes: 0 additions & 6 deletions packages/cli/assets/css-modules/package.json

This file was deleted.

10 changes: 0 additions & 10 deletions packages/cli/assets/postcss/package.json

This file was deleted.

8 changes: 0 additions & 8 deletions packages/cli/assets/postcss/postcss.config.js

This file was deleted.

7 changes: 1 addition & 6 deletions packages/cli/assets/tailwind/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,6 @@
"defaults"
],
"devDependencies": {
"@tailwindcss/forms": "^0.5.3",
"@tailwindcss/typography": "^0.5.9",
"postcss": "^8.4.21",
"postcss-import": "^15.1.0",
"postcss-preset-env": "^8.2.0",
"tailwindcss": "^3.3.0"
"@tailwindcss/vite": "4.0.0-alpha.17"
}
}
10 changes: 0 additions & 10 deletions packages/cli/assets/tailwind/postcss.config.js

This file was deleted.

8 changes: 0 additions & 8 deletions packages/cli/assets/tailwind/tailwind.config.js

This file was deleted.

9 changes: 6 additions & 3 deletions packages/cli/assets/tailwind/tailwind.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
/**
* Configure Tailwind v4 in this file using CSS variables and directives:
* https://tailwindcss.com/blog/tailwindcss-v4-alpha#css-first-configuration
*/

@import 'tailwindcss';
5 changes: 2 additions & 3 deletions packages/cli/assets/vanilla-extract/package.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
{
"comment": "Remix version is automatically updated by the CLI",
"dependencies": {
"@remix-run/css-bundle": "^1"
"@vanilla-extract/css": "^1.15.2"
},
"devDependencies": {
"@vanilla-extract/css": "^1.11.0"
"@vanilla-extract/vite-plugin": "^4.0.10"
}
}
12 changes: 10 additions & 2 deletions packages/cli/oclif.manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -1029,6 +1029,14 @@
"allowNo": false,
"type": "boolean"
},
"styling": {
"description": "Sets the styling strategy to use. One of `tailwind`, `vanilla-extract`, `css-modules`, `postcss`, `none`.",
"env": "SHOPIFY_HYDROGEN_FLAG_STYLING",
"name": "styling",
"hasDynamicHelp": false,
"multiple": false,
"type": "option"
},
"markets": {
"description": "Sets the URL structure to support multiple markets. Must be one of: `subfolders`, `domains`, `subdomains`, `none`. Example: `--markets subfolders`.",
"env": "SHOPIFY_HYDROGEN_FLAG_I18N",
Expand Down Expand Up @@ -1457,12 +1465,12 @@
"aliases": [],
"args": {
"strategy": {
"description": "The CSS strategy to setup. One of tailwind,css-modules,vanilla-extract,postcss",
"description": "The CSS strategy to setup. One of tailwind,vanilla-extract,css-modules,postcss",
"name": "strategy",
"options": [
"tailwind",
"css-modules",
"vanilla-extract",
"css-modules",
"postcss"
]
}
Expand Down
2 changes: 2 additions & 0 deletions packages/cli/src/commands/hydrogen/init.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ describe('init', () => {
shortcut: true,
quickstart: true,
git: true,
styling: 'tailwind',
});
});

Expand All @@ -79,6 +80,7 @@ describe('init', () => {
path: tmpDir,
quickstart: true,
language: 'ts',
styling: 'none',
}),
).resolves.not.toThrow();

Expand Down
17 changes: 17 additions & 0 deletions packages/cli/src/commands/hydrogen/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ import {
flagsToCamelObject,
} from '../../lib/flags.js';
import {checkCurrentCLIVersion} from '../../lib/check-cli-version.js';
import {
STYLING_CHOICES,
type StylingChoice,
} from '../../lib/setups/css/index.js';
import {I18N_CHOICES, type I18nChoice} from '../../lib/setups/i18n/index.js';
import {supressNodeExperimentalWarnings} from '../../lib/process.js';
import {setupTemplate, type InitOptions} from '../../lib/onboarding/index.js';
Expand Down Expand Up @@ -38,6 +42,7 @@ export default class Init extends Command {
description: 'Use mock.shop as the data source for the storefront.',
env: 'SHOPIFY_HYDROGEN_FLAG_MOCK_DATA',
}),
...commonFlags.styling,
...commonFlags.markets,
...commonFlags.shortcut,
routes: Flags.boolean({
Expand Down Expand Up @@ -94,6 +99,17 @@ export async function runInit(
);
}

if (
options.styling &&
!STYLING_CHOICES.includes(options.styling as StylingChoice)
) {
throw new AbortError(
`Invalid styling strategy: ${
options.styling
}. Must be one of ${STYLING_CHOICES.join(', ')}`,
);
}

options.git ??= true;

/**
Expand All @@ -109,6 +125,7 @@ export async function runInit(
options.path ??= './hydrogen-quickstart';
options.routes ??= true;
options.shortcut ??= true;
options.styling ??= 'tailwind';
}

const showUpgrade = await checkCurrentCLIVersion();
Expand Down
49 changes: 40 additions & 9 deletions packages/cli/src/commands/hydrogen/setup/css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,25 @@ import {
flagsToCamelObject,
} from '../../../lib/flags.js';
import Command from '@shopify/cli-kit/node/base-command';
import {renderSuccess, renderTasks} from '@shopify/cli-kit/node/ui';
import {
renderSuccess,
renderTasks,
renderWarning,
} from '@shopify/cli-kit/node/ui';
import {
getPackageManager,
installNodeModules,
} from '@shopify/cli-kit/node/node-package-manager';
import {Args} from '@oclif/core';
import {getRemixConfig, hasRemixConfigFile} from '../../../lib/remix-config.js';
import {
setupCssStrategy,
SETUP_CSS_STRATEGIES,
CSS_STRATEGY_NAME_MAP,
CSS_STRATEGY_HELP_URL_MAP,
type CssStrategy,
renderCssPrompt,
} from '../../../lib/setups/css/index.js';
import {getViteConfig} from '../../../lib/vite-config.js';
import {AbortError} from '@shopify/cli-kit/node/error';

export default class SetupCSS extends Command {
Expand Down Expand Up @@ -64,21 +69,30 @@ export async function runSetupCSS({
force?: boolean;
installDeps: boolean;
}) {
if (!(await hasRemixConfigFile(directory))) {
const viteConfig = await getViteConfig(directory).catch(() => null);
if (!viteConfig) {
throw new AbortError(
'No remix.config.js file found. This command is not supported in Vite projects.',
'No Vite config found. This command is only supported in Vite projects.',
);
}

const remixConfigPromise = getRemixConfig(directory);
const {remixConfig} = viteConfig;

const strategy = flagStrategy ? flagStrategy : await renderCssPrompt();

const remixConfig = await remixConfigPromise;
if (strategy === 'css-modules' || strategy === 'postcss') {
renderSuccess({
headline: `Vite works out of the box with ${CSS_STRATEGY_NAME_MAP[strategy]}.`,
body: `See the Vite documentation for more information:\n${CSS_STRATEGY_HELP_URL_MAP[strategy]}`,
});

return;
}

const setupOutput = await setupCssStrategy(strategy, remixConfig, force);
if (!setupOutput) return;

const {workPromise, generatedAssets, helpUrl} = setupOutput;
const {workPromise, generatedAssets, needsInstallDeps} = setupOutput;

const tasks = [
{
Expand All @@ -89,7 +103,9 @@ export async function runSetupCSS({
},
];

if (installDeps) {
let isNpm = false;

if (installDeps && needsInstallDeps) {
const gettingPkgManagerPromise = getPackageManager(
remixConfig.rootDirectory,
);
Expand All @@ -98,6 +114,8 @@ export async function runSetupCSS({
title: 'Installing new dependencies',
task: async () => {
const packageManager = await gettingPkgManagerPromise;
isNpm = packageManager === 'npm' || packageManager === 'unknown';

await installNodeModules({
directory: remixConfig.rootDirectory,
packageManager,
Expand All @@ -116,6 +134,19 @@ export async function runSetupCSS({
? 'You can now modify CSS configuration in the following files:\n' +
generatedAssets.map((file) => ` - ${file}`).join('\n') +
'\n'
: '') + `\nFor more information, visit ${helpUrl}.`,
: '') +
`\nFor more information, visit ${CSS_STRATEGY_HELP_URL_MAP[strategy]}`,
});

// Due to a bug in NPM related to optional dependencies in Tailwind,
// we need to reinstall dependencies to fix node_modules:
// https://github.com/npm/cli/issues/4828
if (needsInstallDeps && isNpm && strategy === 'tailwind') {
renderWarning({
body: [
'Due to a bug in NPM, you might need to reinstall dependencies again.\nRun',
{command: 'npm install'},
],
});
}
}
2 changes: 0 additions & 2 deletions packages/cli/src/lib/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,7 @@ export const ASSETS_STARTER_DIR_ROUTES = 'routes';

export type AssetsDir =
| 'tailwind'
| 'css-modules'
| 'vanilla-extract'
| 'postcss'
| 'vite'
| 'i18n'
| 'routes'
Expand Down
10 changes: 10 additions & 0 deletions packages/cli/src/lib/flags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {renderInfo} from '@shopify/cli-kit/node/ui';
import {normalizeStoreFqdn} from '@shopify/cli-kit/node/context/fqdn';
import colors from '@shopify/cli-kit/node/colors';
import type {CamelCasedProperties, PartialDeep} from 'type-fest';
import {STYLING_CHOICES} from './setups/css/index.js';
import {I18N_CHOICES} from './setups/i18n/index.js';

export const DEFAULT_APP_PORT = 3000;
Expand Down Expand Up @@ -100,6 +101,15 @@ export const commonFlags = {
dependsOn: ['codegen'],
}),
},
styling: {
styling: Flags.string({
description: `Sets the styling strategy to use. One of ${STYLING_CHOICES.map(
(item) => `\`${item}\``,
).join(', ')}.`,
choices: STYLING_CHOICES,
env: 'SHOPIFY_HYDROGEN_FLAG_STYLING',
}),
},
markets: {
markets: Flags.string({
description: `Sets the URL structure to support multiple markets. Must be one of: ${I18N_CHOICES.map(
Expand Down
11 changes: 5 additions & 6 deletions packages/cli/src/lib/onboarding/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -410,10 +410,6 @@ export async function handleLanguage(
};
}

// Extract this in a variable to avoid TS issues.
// TODO: Remove this when CSS is supported in Vite
const isCssDisabled: boolean = true;

/**
* Prompts the user to select a CSS strategy.
* @returns The chosen strategy name and a function that sets up the CSS strategy.
Expand All @@ -423,8 +419,6 @@ export async function handleCssStrategy(
controller: AbortController,
flagStyling?: StylingChoice,
) {
if (isCssDisabled) return {};

const selection =
flagStyling ??
(await renderCssPrompt({
Expand All @@ -438,6 +432,11 @@ export async function handleCssStrategy(
cssStrategy,
async setupCss() {
if (cssStrategy) {
if (cssStrategy === 'postcss' || cssStrategy === 'css-modules') {
// Nothing to do in Vite projects
return;
}

const result = await setupCssStrategy(
cssStrategy,
{
Expand Down
11 changes: 6 additions & 5 deletions packages/cli/src/lib/setups/css/assets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,16 @@ import {joinPath} from '@shopify/cli-kit/node/path';
import {renderConfirmationPrompt} from '@shopify/cli-kit/node/ui';
import {type AssetsDir, getAssetsDir} from '../../build.js';

export type CssStrategy = Extract<
AssetsDir,
'tailwind' | 'css-modules' | 'vanilla-extract' | 'postcss'
>;
export type CssStrategy =
| 'tailwind'
| 'css-modules'
| 'vanilla-extract'
| 'postcss';

export const SETUP_CSS_STRATEGIES: CssStrategy[] = [
'tailwind',
'css-modules',
'vanilla-extract',
'css-modules',
'postcss',
];

Expand Down
4 changes: 1 addition & 3 deletions packages/cli/src/lib/setups/css/common.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
export type CssSetupResult = {
workPromise: Promise<unknown>;
generatedAssets: string[];
helpUrl: string;
needsInstallDeps: boolean;
};

export type CssSetupConfig = {
rootDirectory: string;
appDirectory: string;
tailwind?: boolean;
postcss?: boolean;
};
Loading

0 comments on commit c269065

Please sign in to comment.