Skip to content

Commit

Permalink
Merge branch 'canary' into feature/with-styled-components-rtl
Browse files Browse the repository at this point in the history
  • Loading branch information
Timer committed Jan 14, 2020
2 parents 9a2d496 + 415a9b6 commit 1e8af3f
Show file tree
Hide file tree
Showing 6 changed files with 146 additions and 47 deletions.
146 changes: 115 additions & 31 deletions docs/basic-features/built-in-css-support.md
@@ -1,17 +1,126 @@
---
description: Next.js includes styled-jsx by default for isolated and scoped CSS support, but you can also use any other CSS-in-JS solution!. Learn more here.
description: Next.js supports including CSS files as Global CSS or CSS Modules, using `styled-jsx` for CSS-in-JS, or any other CSS-in-JS solution! Learn more here.
---

# Built-in CSS Support
# Built-In CSS Support

Next.js allows you to import CSS files from a JavaScript file.
This is possible because Next.js extends the concept of [`import`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import) beyond JavaScript.

## Adding a Global Stylesheet

To add a stylesheet to your application, import the CSS file within `pages/_app.js`.

For example, consider the following stylesheet named `styles.css`:

```css
body {
font-family: 'SF Pro Text', 'SF Pro Icons', system-ui;
padding: 20px 20px 60px;
max-width: 680px;
margin: 0 auto;
}
```

Create a [`pages/_app.js` file](https://nextjs.org/docs/advanced-features/custom-app) if not already present.
Then, [`import`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import) the `styles.css` file.

```jsx
import '../styles.css'

// This default export is required in a new `pages/_app.js` file.
export default function MyApp({ Component, pageProps }) {
return <Component {...pageProps} />
}
```

These styles (`styles.css`) will apply to all pages and components in your application.
Due to the global nature of stylesheets, and to avoid conflicts, you may **only import them inside [`pages/_app.js`](https://nextjs.org/docs/advanced-features/custom-app)**.

In development, expressing stylesheets this way allows your styles to be hot reloaded as you edit them—meaning you can keep application state.

In production, all CSS files will be automatically concatenated into a single minified `.css` file.

## Adding Component-Level CSS

Next.js supports [CSS Modules](https://github.com/css-modules/css-modules) using the `[name].module.css` file naming convention.

CSS Modules locally scope CSS by automatically creating a unique class name.
This allows you to use the same CSS class name in different files without worrying about collisions.

This behavior makes CSS Modules the ideal way to include component-level CSS.
CSS Module files **can be imported anywhere in your application**.

For example, consider a reusable `Button` component in the `components/` folder:

First, create `components/Button.module.css` with the following content:

```css
/*
You do not need to worry about .error {} colliding with any other `.css` or
`.module.css` files!
*/
.error {
color: white;
background-color: red;
}
```

Then, create `components/Button.js`, importing and using the above CSS file:

```jsx
import styles from './Button.module.css'

export function Button() {
return (
<button
type="button"
// Note how the "error" class is accessed as a property on the imported
// `styles` object.
className={styles.error}
>
Destroy
</button>
)
}
```

CSS Modules are an _optional feature_ and are **only enabled for files with the `.module.css` extension**.
Regular `<link>` stylesheets and global CSS files are still supported.

In production, all CSS Module files will be automatically concatenated into **many minified and code-split** `.css` files.
These `.css` files represent hot execution paths in your application, ensuring the minimal amount of CSS is loaded for your application to paint.

## CSS-in-JS

<details>
<summary><b>Examples</b></summary>
<ul>
<li><a href="https://github.com/zeit/next.js/tree/canary/examples/basic-css">Basic CSS</a></li>
<li><a href="https://github.com/zeit/next.js/tree/canary/examples/basic-css">Styled JSX</a></li>
<li><a href="https://github.com/zeit/next.js/tree/canary/examples/with-styled-components">Styled Components</a></li>
<li><a href="https://github.com/zeit/next.js/tree/canary/examples/with-styletron">Styletron</a></li>
<li><a href="https://github.com/zeit/next.js/tree/canary/examples/with-glamor">Glamor</a></li>
<li><a href="https://github.com/zeit/next.js/tree/canary/examples/with-cxs">Cxs</a></li>
<li><a href="https://github.com/zeit/next.js/tree/canary/examples/with-aphrodite">Aphrodite</a></li>
<li><a href="https://github.com/zeit/next.js/tree/canary/examples/with-fela">Fela</a></li>
</ul>
</details>

We bundle [styled-jsx](https://github.com/zeit/styled-jsx) to provide support for isolated scoped CSS. The aim is to support "shadow CSS" similar to Web Components, which unfortunately [do not support server-rendering and are JS-only](https://github.com/w3c/webcomponents/issues/71).
It's possible to use any existing CSS-in-JS solution.
The simplest one is inline styles:

```jsx
function HiThere() {
return <p style={{ color: 'red' }}>hi there</p>
}

export default HiThere
```

We bundle [styled-jsx](https://github.com/zeit/styled-jsx) to provide support for isolated scoped CSS.
The aim is to support "shadow CSS" similar to Web Components, which unfortunately [do not support server-rendering and are JS-only](https://github.com/w3c/webcomponents/issues/71).

See the above examples for other popular CSS-in-JS solutions (like Styled Components).

A component using `styled-jsx` looks like this:

Expand Down Expand Up @@ -48,35 +157,10 @@ export default HelloWorld

Please see the [styled-jsx documentation](https://github.com/zeit/styled-jsx) for more examples.

## CSS-in-JS

<details>
<summary><b>Examples</b></summary>
<ul>
<li><a href="https://github.com/zeit/next.js/tree/canary/examples/with-styled-components">Styled components</a></li>
<li><a href="https://github.com/zeit/next.js/tree/canary/examples/with-styletron">Styletron</a></li>
<li><a href="https://github.com/zeit/next.js/tree/canary/examples/with-glamor">Glamor</a></li>
<li><a href="https://github.com/zeit/next.js/tree/canary/examples/with-cxs">Cxs</a></li>
<li><a href="https://github.com/zeit/next.js/tree/canary/examples/with-aphrodite">Aphrodite</a></li>
<li><a href="https://github.com/zeit/next.js/tree/canary/examples/with-fela">Fela</a></li>
</ul>
</details>

It's possible to use any existing CSS-in-JS solution. The simplest one is inline styles:

```jsx
function HiThere() {
return <p style={{ color: 'red' }}>hi there</p>
}

export default HiThere
```

## CSS Plugins
## Sass, Less, and Stylus Support

To support importing `.css``.scss``.less` or `.styl` files you can use the following modules, which configure sensible defaults for server rendered applications:
To support importing `.scss``.less` or `.styl` files you can use the following plugins:

- [@zeit/next-css](https://github.com/zeit/next-plugins/tree/master/packages/next-css)
- [@zeit/next-sass](https://github.com/zeit/next-plugins/tree/master/packages/next-sass)
- [@zeit/next-less](https://github.com/zeit/next-plugins/tree/master/packages/next-less)
- [@zeit/next-stylus](https://github.com/zeit/next-plugins/tree/master/packages/next-stylus)
8 changes: 6 additions & 2 deletions docs/deployment.md
Expand Up @@ -60,11 +60,11 @@ HTTPS is enabled by default and doesn't require extra configuration.

#### From a git repository

You can link your project in [GitHub](https://zeit.co/new), [GitLab](https://zeit.co/new), or [Bitbucket](https://zeit.co/new) through the [web interface](https://zeit.co/new). This will automatically set up deployment previews for pull requests and commits.
You can link your project in [GitHub](https://zeit.co/new), [GitLab](https://zeit.co/new), or [Bitbucket](https://zeit.co/new) through the [web interface](https://zeit.co/new). This will automatically set up deployment previews for pull requests and commits. To learn more about ZEIT Now’s Git integration, take a look at [our documentation here](https://zeit.co/docs/v2/git-integration/).

#### Through the ZEIT Now CLI

You can install the command line tool using npm:
You can install [Now CLI](https://zeit.co/download) from either npm or Yarn. Using npm, run the following command from your terminal:

```bash
npm install -g now
Expand All @@ -78,6 +78,10 @@ now

You will receive a unique link similar to the following: https://your-project.username.now.sh.

#### Custom domains

Once deployed on ZEIT Now, your projects can be assigned to a custom domain of your choice. To learn more, take a look at [our documentation here](https://zeit.co/docs/v2/custom-domains/).

## Self hosting

Next.js can be deployed to any hosting provider that supports Node.js. In order to self-host there are two commands: `next build` and `next start`.
Expand Down
2 changes: 0 additions & 2 deletions examples/basic-export/README.md
Expand Up @@ -40,8 +40,6 @@ yarn dev
Deploy it to the cloud with [now](https://zeit.co/now) ([download](https://zeit.co/download)):

```bash
npm run export
cd out
now
```

Expand Down
5 changes: 2 additions & 3 deletions examples/basic-export/package.json
Expand Up @@ -3,9 +3,8 @@
"version": "1.0.0",
"scripts": {
"dev": "next",
"build": "next build",
"start": "next start",
"export": "next export"
"build": "next build && next export",
"start": "next start"
},
"dependencies": {
"next": "latest",
Expand Down
3 changes: 1 addition & 2 deletions packages/next/build/webpack-config.ts
Expand Up @@ -432,8 +432,7 @@ export default async function getBaseWebpackConfig(
// are relative to requests we've already resolved here.
// Absolute requires (require('/foo')) are extremely uncommon, but
// also have no need for customization as they're already resolved.
const start = request.charAt(0)
if (start === '.' || start === '/') {
if (request.startsWith('.') || request.startsWith('/')) {
return callback()
}

Expand Down
29 changes: 22 additions & 7 deletions packages/next/build/webpack/plugins/next-esm-plugin.ts
Expand Up @@ -213,38 +213,53 @@ export default class NextEsmPlugin implements Plugin {
compilation.namedChunkGroups
)

const unnamedChunks: compilation.Chunk[] = []
const childChunkFileMap = childCompilation.chunks.reduce(
(
chunkMap: { [key: string]: compilation.Chunk },
chunk: compilation.Chunk
) => {
chunkMap[chunk.name] = chunk
// Dynamic chunks may not have a name. It'll be null in such cases
if (chunk.name === null) {
unnamedChunks.push(chunk)
} else {
chunkMap[chunk.name] = chunk
}

return chunkMap
},
{}
)

// Merge files from similar chunks
// Merge chunks - merge the files of chunks with the same name
compilation.chunks.forEach((chunk: compilation.Chunk) => {
const childChunk = childChunkFileMap[chunk.name]

if (childChunk?.files) {
// Do not merge null named chunks since they are different
if (chunk.name !== null && childChunk?.files) {
delete childChunkFileMap[chunk.name]
chunk.files.push(
...childChunk.files.filter((v: any) => !chunk.files.includes(v))
)
}
})

// Add modern only chunks
compilation.chunks.push(...Object.values(childChunkFileMap))
// Add modern only chunks into the main compilation
compilation.chunks.push(
...Object.values(childChunkFileMap),
...unnamedChunks
)

// Place modern only chunk inside the right entry point
// Place modern only (unmerged) chunks inside the right entry point
compilation.entrypoints.forEach((entryPoint, entryPointName) => {
const childEntryPoint = childCompilation.entrypoints.get(entryPointName)

childEntryPoint.chunks.forEach((chunk: compilation.Chunk) => {
if (childChunkFileMap.hasOwnProperty(chunk.name)) {
if (
// Add null named dynamic chunks since they weren't merged
chunk.name === null ||
childChunkFileMap.hasOwnProperty(chunk.name)
) {
entryPoint.chunks.push(chunk)
}
})
Expand Down

0 comments on commit 1e8af3f

Please sign in to comment.