diff --git a/examples/with-emotion-swc/.gitignore b/examples/with-emotion-swc/.gitignore
new file mode 100644
index 0000000000000..1437c53f70bc2
--- /dev/null
+++ b/examples/with-emotion-swc/.gitignore
@@ -0,0 +1,34 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+/.pnp
+.pnp.js
+
+# 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
+.env.development.local
+.env.test.local
+.env.production.local
+
+# vercel
+.vercel
diff --git a/examples/with-emotion-swc/README.md b/examples/with-emotion-swc/README.md
new file mode 100644
index 0000000000000..12b4f677a8d04
--- /dev/null
+++ b/examples/with-emotion-swc/README.md
@@ -0,0 +1,31 @@
+# Emotion Example
+
+Extract and inline critical css with
+[@emotion/css](https://github.com/emotion-js/emotion/tree/master/packages/css),
+[@emotion/server](https://github.com/emotion-js/emotion/tree/master/packages/server),
+[@emotion/react](https://github.com/emotion-js/emotion/tree/master/packages/react),
+and [@emotion/styled](https://github.com/emotion-js/emotion/tree/master/packages/styled).
+
+## Preview
+
+Preview the example live on [StackBlitz](http://stackblitz.com/):
+
+[![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/vercel/next.js/tree/canary/examples/with-emotion)
+
+## Deploy your own
+
+Deploy the example using [Vercel](https://vercel.com?utm_source=github&utm_medium=readme&utm_campaign=next-example):
+
+[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/git/external?repository-url=https://github.com/vercel/next.js/tree/canary/examples/with-emotion&project-name=with-emotion&repository-name=with-emotion)
+
+## How to use
+
+Execute [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app) with [npm](https://docs.npmjs.com/cli/init) or [Yarn](https://yarnpkg.com/lang/en/docs/cli/create/) to bootstrap the example:
+
+```bash
+npx create-next-app --example with-emotion with-emotion-app
+# or
+yarn create next-app --example with-emotion with-emotion-app
+```
+
+Deploy it to the cloud with [Vercel](https://vercel.com/new?utm_source=github&utm_medium=readme&utm_campaign=next-example) ([Documentation](https://nextjs.org/docs/deployment)).
diff --git a/examples/with-emotion-swc/next.config.js b/examples/with-emotion-swc/next.config.js
new file mode 100644
index 0000000000000..589e094972ac0
--- /dev/null
+++ b/examples/with-emotion-swc/next.config.js
@@ -0,0 +1,12 @@
+/** @type {import('next').NextConfig} */
+
+const nextConfig = {
+ reactStrictMode: true,
+ compiler: {
+ emotion: {
+ enabled: true,
+ },
+ },
+}
+
+module.exports = nextConfig
diff --git a/examples/with-emotion-swc/package.json b/examples/with-emotion-swc/package.json
new file mode 100644
index 0000000000000..411e3fcb8efb8
--- /dev/null
+++ b/examples/with-emotion-swc/package.json
@@ -0,0 +1,15 @@
+{
+ "private": true,
+ "scripts": {
+ "dev": "next",
+ "build": "next build",
+ "start": "next start"
+ },
+ "dependencies": {
+ "@emotion/react": "11.8.1",
+ "@emotion/styled": "11.8.1",
+ "next": "latest",
+ "react": "17.0.2",
+ "react-dom": "17.0.2"
+ }
+}
diff --git a/examples/with-emotion-swc/pages/_app.js b/examples/with-emotion-swc/pages/_app.js
new file mode 100644
index 0000000000000..aaa1325721214
--- /dev/null
+++ b/examples/with-emotion-swc/pages/_app.js
@@ -0,0 +1,10 @@
+import { globalStyles } from '../shared/styles'
+
+const App = ({ Component, pageProps }) => (
+ <>
+ {globalStyles}
+
+ >
+)
+
+export default App
diff --git a/examples/with-emotion-swc/pages/index.js b/examples/with-emotion-swc/pages/index.js
new file mode 100644
index 0000000000000..e1300eb342ad0
--- /dev/null
+++ b/examples/with-emotion-swc/pages/index.js
@@ -0,0 +1,14 @@
+import { Animated, Basic, bounce, Combined, Pink } from '../shared/styles'
+
+const Home = () => (
+
+
Cool Styles
+
Pink text
+
+ With :hover
.
+
+
Let's bounce.
+
+)
+
+export default Home
diff --git a/examples/with-emotion-swc/shared/styles.js b/examples/with-emotion-swc/shared/styles.js
new file mode 100644
index 0000000000000..cb9720bbfeba1
--- /dev/null
+++ b/examples/with-emotion-swc/shared/styles.js
@@ -0,0 +1,72 @@
+import { css, Global, keyframes } from '@emotion/react'
+import styled from '@emotion/styled'
+
+export const globalStyles = (
+
+)
+
+export const basicStyles = css({
+ backgroundColor: 'white',
+ color: 'cornflowerblue',
+ border: '1px solid lightgreen',
+ borderRight: 'none',
+ borderBottom: 'none',
+ boxShadow: '5px 5px 0 0 lightgreen, 10px 10px 0 0 lightyellow',
+ transition: 'all 0.1s linear',
+ margin: '3rem 0',
+ padding: '1rem 0.5rem',
+})
+
+export const hoverStyles = css`
+ &:hover {
+ color: white;
+ background-color: lightgray;
+ border-color: aqua;
+ box-shadow: -15px -15px 0 0 aqua, -30px -30px 0 0 cornflowerblue;
+ }
+`
+export const bounce = keyframes`
+ from {
+ transform: scale(1.01);
+ }
+ to {
+ transform: scale(0.99);
+ }
+`
+
+export const Basic = styled.div`
+ ${basicStyles};
+`
+
+export const Combined = styled.div`
+ ${basicStyles};
+ ${hoverStyles};
+ & code {
+ background-color: linen;
+ }
+`
+
+export const Pink = styled.div(basicStyles, {
+ color: 'hotpink',
+})
+
+export const Animated = styled.div`
+ ${basicStyles};
+ ${hoverStyles};
+ & code {
+ background-color: linen;
+ }
+ animation: ${({ animation }) => animation} 0.2s infinite ease-in-out alternate;
+`
diff --git a/package.json b/package.json
index 162cce7f1e6c4..0de871fbaeeea 100644
--- a/package.json
+++ b/package.json
@@ -148,9 +148,9 @@
"react-dom": "17.0.2",
"react-dom-18": "npm:react-dom@18.0.0-rc.0",
"react-ssr-prepass": "1.0.8",
+ "react-virtualized": "9.22.3",
"relay-compiler": "13.0.2",
"relay-runtime": "13.0.2",
- "react-virtualized": "9.22.3",
"release": "6.3.0",
"request-promise-core": "1.1.2",
"resolve-from": "5.0.0",
diff --git a/packages/next-swc/Cargo.lock b/packages/next-swc/Cargo.lock
index 69cba72cb2d90..2cc86cfcfaf21 100644
--- a/packages/next-swc/Cargo.lock
+++ b/packages/next-swc/Cargo.lock
@@ -805,6 +805,7 @@ checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54"
name = "next-swc"
version = "0.0.0"
dependencies = [
+ "base64 0.13.0",
"byteorder",
"chrono",
"easy-error",
@@ -1355,9 +1356,9 @@ checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
[[package]]
name = "relative-path"
-version = "1.5.0"
+version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f9629de8974fd69c97684736786b807edd3da456d3e3f95341dd9d4cbd8f5ad6"
+checksum = "a49a831dc1e13c9392b660b162333d4cb0033bbbdfe6a1687177e59e89037c86"
[[package]]
name = "remove_dir_all"
diff --git a/packages/next-swc/crates/core/Cargo.toml b/packages/next-swc/crates/core/Cargo.toml
index e61bcb720069d..c069399b8213b 100644
--- a/packages/next-swc/crates/core/Cargo.toml
+++ b/packages/next-swc/crates/core/Cargo.toml
@@ -7,6 +7,7 @@ version = "0.0.0"
crate-type = ["cdylib", "rlib"]
[dependencies]
+base64 = "0.13"
byteorder = "1"
chrono = "0.4"
easy-error = "1.0.0"
diff --git a/packages/next-swc/crates/core/src/emotion/mod.rs b/packages/next-swc/crates/core/src/emotion/mod.rs
index a26456c60fe19..579e5e45de965 100644
--- a/packages/next-swc/crates/core/src/emotion/mod.rs
+++ b/packages/next-swc/crates/core/src/emotion/mod.rs
@@ -1,10 +1,11 @@
-use std::path::PathBuf;
+use std::path::{Path, PathBuf};
use std::sync::Arc;
use fxhash::FxHashMap;
use once_cell::sync::Lazy;
use serde::{Deserialize, Serialize};
-use swc_common::{SourceMap, DUMMY_SP};
+use swc::sourcemap::{RawToken, SourceMap as RawSourcemap};
+use swc_common::{BytePos, SourceMap, DUMMY_SP};
use swc_ecmascript::ast::{
ExprOrSpread, Ident, KeyValueProp, Lit, MemberProp, ObjectLit, Pat, Prop, PropName,
PropOrSpread, VarDeclarator,
@@ -35,15 +36,13 @@ static EMOTION_OFFICIAL_LIBRARIES: Lazy> = Lazy::new(||
});
#[derive(Debug, Clone, Serialize, Deserialize)]
+#[serde(rename_all = "camelCase")]
pub struct EmotionOptions {
pub enabled: Option,
pub sourcemap: Option,
pub auto_label: Option,
pub label_format: Option,
- pub css_prop_optimization: Option,
pub custom_modules: Option>,
- pub jsx_factory: Option,
- pub jsx_import_source: Option,
}
impl Default for EmotionOptions {
@@ -53,10 +52,7 @@ impl Default for EmotionOptions {
sourcemap: Some(true),
auto_label: Some(true),
label_format: Some("[local]".to_owned()),
- css_prop_optimization: Some(true),
custom_modules: None,
- jsx_import_source: Some("@emotion/react".to_owned()),
- jsx_factory: None,
}
}
}
@@ -102,14 +98,14 @@ struct PackageMeta {
pub fn emotion(
emotion_options: EmotionOptions,
- file_name: &PathBuf,
+ path: &Path,
cm: Arc,
react_jsx_runtime: bool,
es_module_interop: bool,
) -> impl Fold {
EmotionTransformer::new(
emotion_options,
- file_name,
+ path,
cm,
react_jsx_runtime,
es_module_interop,
@@ -134,7 +130,7 @@ pub struct EmotionTransformer {
impl EmotionTransformer {
pub fn new(
options: EmotionOptions,
- path: &PathBuf,
+ path: &Path,
cm: Arc,
react_jsx_runtime: bool,
es_module_interop: bool,
@@ -171,13 +167,15 @@ impl EmotionTransformer {
self.filepath_hash.unwrap()
}
- fn create_label(&self) -> String {
+ fn create_label(&self, with_prefix: bool) -> String {
+ let prefix = if with_prefix { "label:" } else { "" };
let mut label = format!(
- "label:{}",
+ "{}{}",
+ prefix,
self.options
.label_format
.clone()
- .unwrap_or("[local]".to_owned())
+ .unwrap_or_else(|| "[local]".to_owned())
);
if let Some(current_context) = &self.current_context {
label = label.replace("[local]", current_context);
@@ -191,6 +189,35 @@ impl EmotionTransformer {
label
}
+ fn create_sourcemap(&mut self, pos: BytePos) -> Option {
+ if self.options.sourcemap.unwrap_or(false) {
+ let loc = self.cm.get_code_map().lookup_char_pos(pos);
+ let filename = self.filepath.to_str().map(|s| s.to_owned());
+ let cm = RawSourcemap::new(
+ filename.clone(),
+ vec![RawToken {
+ dst_line: 0,
+ dst_col: 0,
+ src_line: loc.line as u32 - 1,
+ src_col: loc.col_display as u32,
+ src_id: 0,
+ name_id: 0,
+ }],
+ Vec::new(),
+ vec![filename.unwrap_or_default()],
+ Some(vec![Some(loc.file.src.to_string())]),
+ );
+ let mut writer = Vec::new();
+ if cm.to_writer(&mut writer).is_ok() {
+ return Some(format!(
+ "/*# sourceMappingURL=data:application/json;charset=utf-8;base64,{} */",
+ base64::encode(writer)
+ ));
+ }
+ }
+ None
+ }
+
// Find the imported name from modules
// These import statements are supported:
// import styled from '@emotion/styled'
@@ -292,12 +319,16 @@ impl Fold for EmotionTransformer {
if self.options.auto_label.unwrap_or(false) {
expr.args.push(ExprOrSpread {
spread: None,
- expr: Box::new(Expr::Lit(Lit::Str(self.create_label().into()))),
+ expr: Box::new(Expr::Lit(Lit::Str(
+ self.create_label(true).into(),
+ ))),
});
}
- if self.options.sourcemap.unwrap_or(false) {
- let _loc = self.cm.get_code_map().lookup_char_pos(expr.span.lo());
- // generate sourcemap
+ if let Some(cm) = self.create_sourcemap(expr.span.lo) {
+ expr.args.push(ExprOrSpread {
+ spread: None,
+ expr: Box::new(Expr::Lit(Lit::Str(cm.into()))),
+ });
}
}
}
@@ -308,33 +339,34 @@ impl Fold for EmotionTransformer {
if let Expr::Ident(i) = callee_exp.as_ref() {
if let Some(package) = self.import_packages.get(i.as_ref()) {
if !c.args.is_empty() && matches!(package.kind, ExprKind::Styled) {
+ let mut args_props = Vec::with_capacity(2);
+ args_props.push(self.create_target_arg_node());
if self.options.auto_label.unwrap_or(false) {
- c.args.push(ExprOrSpread {
+ args_props.push(PropOrSpread::Prop(Box::new(
+ Prop::KeyValue(KeyValueProp {
+ key: PropName::Ident(Ident::new(
+ "label".into(),
+ DUMMY_SP,
+ )),
+ value: Box::new(Expr::Lit(Lit::Str(
+ self.create_label(false).into(),
+ ))),
+ }),
+ )));
+ }
+ if let Some(cm) = self.create_sourcemap(expr.span.lo()) {
+ expr.args.push(ExprOrSpread {
spread: None,
- expr: Box::new(Expr::Object(ObjectLit {
- span: DUMMY_SP,
- props: vec![
- self.create_target_arg_node(),
- PropOrSpread::Prop(Box::new(Prop::KeyValue(
- KeyValueProp {
- key: PropName::Ident(Ident::new(
- "label".into(),
- DUMMY_SP,
- )),
- value: Box::new(Expr::Lit(Lit::Str(
- self.create_label().into(),
- ))),
- },
- ))),
- ],
- })),
+ expr: Box::new(Expr::Lit(Lit::Str(cm.into()))),
});
}
- if self.options.sourcemap.unwrap_or(false) {
- let _loc =
- self.cm.get_code_map().lookup_char_pos(expr.span.lo());
- // generate sourcemap
- }
+ c.args.push(ExprOrSpread {
+ spread: None,
+ expr: Box::new(Expr::Object(ObjectLit {
+ span: DUMMY_SP,
+ props: args_props,
+ })),
+ });
}
}
}
@@ -345,77 +377,74 @@ impl Fold for EmotionTransformer {
Expr::Member(m) => {
if let Expr::Ident(i) = m.obj.as_ref() {
if let Some(package) = self.import_packages.get(i.as_ref()) {
- if self.options.auto_label.unwrap_or(false) {
- match package.kind {
- ExprKind::Css => {
+ match package.kind {
+ ExprKind::Css => {
+ if self.options.auto_label.unwrap_or(false) {
expr.args.push(ExprOrSpread {
spread: None,
expr: Box::new(Expr::Lit(Lit::Str(
- self.create_label().into(),
+ self.create_label(true).into(),
))),
});
}
- ExprKind::Styled => {
- if let MemberProp::Ident(prop) = &m.prop {
- return CallExpr {
- span: expr.span,
- type_args: expr.type_args,
- args: expr.args,
- callee: Callee::Expr(Box::new(Expr::Call(
- CallExpr {
- span: DUMMY_SP,
- type_args: None,
- callee: Callee::Expr(Box::new(
- Expr::Ident(Ident::new(
- i.sym.clone(),
- i.span,
- )),
- )),
- args: vec![
- ExprOrSpread {
- spread: None,
- expr: Box::new(Expr::Lit(
- Lit::Str(prop.as_ref().into()),
- )),
- },
- ExprOrSpread {
- spread: None,
- expr: Box::new(Expr::Object(
- ObjectLit {
- span: DUMMY_SP,
- props: vec![
- self.create_target_arg_node(),
- PropOrSpread::Prop(Box::new(
- Prop::KeyValue(KeyValueProp {
- key: PropName::Ident(
- Ident::new(
- "label".into(),
- DUMMY_SP,
- ),
- ),
- value: Box::new(Expr::Lit(
- Lit::Str(
- self.create_label()
- .into(),
- ),
- )),
- }),
- )),
- ],
- },
- )),
- },
- ],
- },
- ))),
- };
- }
+ if let Some(sm) = self.create_sourcemap(expr.span.lo()) {
+ expr.args.push(ExprOrSpread {
+ spread: None,
+ expr: Box::new(Expr::Lit(Lit::Str(sm.into()))),
+ });
}
}
- if self.options.sourcemap.unwrap_or(false) {
- let _loc =
- self.cm.get_code_map().lookup_char_pos(expr.span.lo());
- // generate sourcemap
+ ExprKind::Styled => {
+ if let MemberProp::Ident(prop) = &m.prop {
+ let mut args_props = Vec::with_capacity(2);
+ args_props.push(self.create_target_arg_node());
+ if self.options.auto_label.unwrap_or(false) {
+ args_props.push(PropOrSpread::Prop(Box::new(
+ Prop::KeyValue(KeyValueProp {
+ key: PropName::Ident(Ident::new(
+ "label".into(),
+ DUMMY_SP,
+ )),
+ value: Box::new(Expr::Lit(Lit::Str(
+ self.create_label(false).into(),
+ ))),
+ }),
+ )));
+ }
+ if let Some(cm) = self.create_sourcemap(expr.span.lo()) {
+ expr.args.push(ExprOrSpread {
+ spread: None,
+ expr: Box::new(Expr::Lit(Lit::Str(cm.into()))),
+ });
+ }
+ return CallExpr {
+ span: expr.span,
+ type_args: expr.type_args,
+ args: expr.args,
+ callee: Callee::Expr(Box::new(Expr::Call(CallExpr {
+ span: DUMMY_SP,
+ type_args: None,
+ callee: Callee::Expr(Box::new(Expr::Ident(
+ Ident::new(i.sym.clone(), i.span),
+ ))),
+ args: vec![
+ ExprOrSpread {
+ spread: None,
+ expr: Box::new(Expr::Lit(Lit::Str(
+ prop.as_ref().into(),
+ ))),
+ },
+ ExprOrSpread {
+ spread: None,
+ expr: Box::new(Expr::Object(ObjectLit {
+ span: DUMMY_SP,
+ props: args_props,
+ })),
+ },
+ ],
+ }))),
+ };
+ }
}
}
}
diff --git a/packages/next-swc/crates/core/tests/fixture/emotion/css-in-callback/output.ts b/packages/next-swc/crates/core/tests/fixture/emotion/css-in-callback/output.ts
index 0e4961b9d54fd..580b6058dd295 100644
--- a/packages/next-swc/crates/core/tests/fixture/emotion/css-in-callback/output.ts
+++ b/packages/next-swc/crates/core/tests/fixture/emotion/css-in-callback/output.ts
@@ -10,27 +10,35 @@ const stylesInCallback = (props: any) =>
background: 'yellow',
width: `${props.scale * 100}px`,
},
- 'label:stylesInCallback'
+ 'label:stylesInCallback',
+ '/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiL1VzZXJzL2xvbmd5aW5hbi93b3Jrc3BhY2UvZ2l0aHViL25leHQuanMvcGFja2FnZXMvbmV4dC1zd2MvY3JhdGVzL2NvcmUvdGVzdHMvZml4dHVyZS9lbW90aW9uL2Nzcy1pbi1jYWxsYmFjay9pbnB1dC50c3giLCJzb3VyY2VzIjpbIi9Vc2Vycy9sb25neWluYW4vd29ya3NwYWNlL2dpdGh1Yi9uZXh0LmpzL3BhY2thZ2VzL25leHQtc3djL2NyYXRlcy9jb3JlL3Rlc3RzL2ZpeHR1cmUvZW1vdGlvbi9jc3MtaW4tY2FsbGJhY2svaW5wdXQudHN4Il0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGNzcyB9IGZyb20gJ0BlbW90aW9uL3JlYWN0J1xuaW1wb3J0IHN0eWxlZCBmcm9tICdAZW1vdGlvbi9zdHlsZWQnXG5pbXBvcnQgeyBQdXJlQ29tcG9uZW50IH0gZnJvbSAncmVhY3QnXG5pbXBvcnQgUmVhY3RET00gZnJvbSAncmVhY3QtZG9tJ1xuXG5jb25zdCBzdHlsZXNJbkNhbGxiYWNrID0gKHByb3BzOiBhbnkpID0+XG4gIGNzcyh7XG4gICAgY29sb3I6ICdyZWQnLFxuICAgIGJhY2tncm91bmQ6ICd5ZWxsb3cnLFxuICAgIHdpZHRoOiBgJHtwcm9wcy5zY2FsZSAqIDEwMH1weGAsXG4gIH0pXG5cbmNvbnN0IHN0eWxlcyA9IGNzcyh7XG4gIGNvbG9yOiAncmVkJyxcbiAgd2lkdGg6ICcyMHB4Jyxcbn0pXG5cbmNvbnN0IERpY0NvbnRhaW5lciA9IHN0eWxlZC5kaXYoe1xuICBiYWNrZ3JvdW5kOiAncmVkJyxcbn0pXG5cbmNvbnN0IFNwYW5Db250YWluZXIgPSBzdHlsZWQoJ3NwYW4nKSh7XG4gIGJhY2tncm91bmQ6ICd5ZWxsb3cnLFxufSlcblxuY29uc3QgQ29udGFpbmVyID0gc3R5bGVkKCdidXR0b24nKWBcbiAgJHtzdHlsZXNJbkNhbGxiYWNrfVxuICAkeygpID0+XG4gICAgY3NzKHtcbiAgICAgIGJhY2tncm91bmQ6ICdyZWQnLFxuICAgIH0pfVxuYFxuZXhwb3J0IGNsYXNzIFNpbXBsZUNvbXBvbmVudCBleHRlbmRzIFB1cmVDb21wb25lbnQge1xuICByZW5kZXIoKSB7XG4gICAgcmV0dXJuIChcbiAgICAgIDxDb250YWluZXI+XG4gICAgICAgIDxzcGFuPmhlbGxvPC9zcGFuPlxuICAgICAgPC9Db250YWluZXI+XG4gICAgKVxuICB9XG59XG5cblJlYWN0RE9NLnJlbmRlcig8U2ltcGxlQ29tcG9uZW50IC8+LCBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCcjYXBwJykpXG4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBTUUifQ== */'
)
const styles = css(
{
color: 'red',
width: '20px',
},
- 'label:styles'
+ 'label:styles',
+ '/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiL1VzZXJzL2xvbmd5aW5hbi93b3Jrc3BhY2UvZ2l0aHViL25leHQuanMvcGFja2FnZXMvbmV4dC1zd2MvY3JhdGVzL2NvcmUvdGVzdHMvZml4dHVyZS9lbW90aW9uL2Nzcy1pbi1jYWxsYmFjay9pbnB1dC50c3giLCJzb3VyY2VzIjpbIi9Vc2Vycy9sb25neWluYW4vd29ya3NwYWNlL2dpdGh1Yi9uZXh0LmpzL3BhY2thZ2VzL25leHQtc3djL2NyYXRlcy9jb3JlL3Rlc3RzL2ZpeHR1cmUvZW1vdGlvbi9jc3MtaW4tY2FsbGJhY2svaW5wdXQudHN4Il0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGNzcyB9IGZyb20gJ0BlbW90aW9uL3JlYWN0J1xuaW1wb3J0IHN0eWxlZCBmcm9tICdAZW1vdGlvbi9zdHlsZWQnXG5pbXBvcnQgeyBQdXJlQ29tcG9uZW50IH0gZnJvbSAncmVhY3QnXG5pbXBvcnQgUmVhY3RET00gZnJvbSAncmVhY3QtZG9tJ1xuXG5jb25zdCBzdHlsZXNJbkNhbGxiYWNrID0gKHByb3BzOiBhbnkpID0+XG4gIGNzcyh7XG4gICAgY29sb3I6ICdyZWQnLFxuICAgIGJhY2tncm91bmQ6ICd5ZWxsb3cnLFxuICAgIHdpZHRoOiBgJHtwcm9wcy5zY2FsZSAqIDEwMH1weGAsXG4gIH0pXG5cbmNvbnN0IHN0eWxlcyA9IGNzcyh7XG4gIGNvbG9yOiAncmVkJyxcbiAgd2lkdGg6ICcyMHB4Jyxcbn0pXG5cbmNvbnN0IERpY0NvbnRhaW5lciA9IHN0eWxlZC5kaXYoe1xuICBiYWNrZ3JvdW5kOiAncmVkJyxcbn0pXG5cbmNvbnN0IFNwYW5Db250YWluZXIgPSBzdHlsZWQoJ3NwYW4nKSh7XG4gIGJhY2tncm91bmQ6ICd5ZWxsb3cnLFxufSlcblxuY29uc3QgQ29udGFpbmVyID0gc3R5bGVkKCdidXR0b24nKWBcbiAgJHtzdHlsZXNJbkNhbGxiYWNrfVxuICAkeygpID0+XG4gICAgY3NzKHtcbiAgICAgIGJhY2tncm91bmQ6ICdyZWQnLFxuICAgIH0pfVxuYFxuZXhwb3J0IGNsYXNzIFNpbXBsZUNvbXBvbmVudCBleHRlbmRzIFB1cmVDb21wb25lbnQge1xuICByZW5kZXIoKSB7XG4gICAgcmV0dXJuIChcbiAgICAgIDxDb250YWluZXI+XG4gICAgICAgIDxzcGFuPmhlbGxvPC9zcGFuPlxuICAgICAgPC9Db250YWluZXI+XG4gICAgKVxuICB9XG59XG5cblJlYWN0RE9NLnJlbmRlcig8U2ltcGxlQ29tcG9uZW50IC8+LCBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCcjYXBwJykpXG4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBWWUifQ== */'
)
const DicContainer = styled('div', {
target: 'ep3ww290',
- label: 'label:DicContainer',
-})({
- background: 'red',
-})
+ label: 'DicContainer',
+})(
+ {
+ background: 'red',
+ },
+ '/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiL1VzZXJzL2xvbmd5aW5hbi93b3Jrc3BhY2UvZ2l0aHViL25leHQuanMvcGFja2FnZXMvbmV4dC1zd2MvY3JhdGVzL2NvcmUvdGVzdHMvZml4dHVyZS9lbW90aW9uL2Nzcy1pbi1jYWxsYmFjay9pbnB1dC50c3giLCJzb3VyY2VzIjpbIi9Vc2Vycy9sb25neWluYW4vd29ya3NwYWNlL2dpdGh1Yi9uZXh0LmpzL3BhY2thZ2VzL25leHQtc3djL2NyYXRlcy9jb3JlL3Rlc3RzL2ZpeHR1cmUvZW1vdGlvbi9jc3MtaW4tY2FsbGJhY2svaW5wdXQudHN4Il0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGNzcyB9IGZyb20gJ0BlbW90aW9uL3JlYWN0J1xuaW1wb3J0IHN0eWxlZCBmcm9tICdAZW1vdGlvbi9zdHlsZWQnXG5pbXBvcnQgeyBQdXJlQ29tcG9uZW50IH0gZnJvbSAncmVhY3QnXG5pbXBvcnQgUmVhY3RET00gZnJvbSAncmVhY3QtZG9tJ1xuXG5jb25zdCBzdHlsZXNJbkNhbGxiYWNrID0gKHByb3BzOiBhbnkpID0+XG4gIGNzcyh7XG4gICAgY29sb3I6ICdyZWQnLFxuICAgIGJhY2tncm91bmQ6ICd5ZWxsb3cnLFxuICAgIHdpZHRoOiBgJHtwcm9wcy5zY2FsZSAqIDEwMH1weGAsXG4gIH0pXG5cbmNvbnN0IHN0eWxlcyA9IGNzcyh7XG4gIGNvbG9yOiAncmVkJyxcbiAgd2lkdGg6ICcyMHB4Jyxcbn0pXG5cbmNvbnN0IERpY0NvbnRhaW5lciA9IHN0eWxlZC5kaXYoe1xuICBiYWNrZ3JvdW5kOiAncmVkJyxcbn0pXG5cbmNvbnN0IFNwYW5Db250YWluZXIgPSBzdHlsZWQoJ3NwYW4nKSh7XG4gIGJhY2tncm91bmQ6ICd5ZWxsb3cnLFxufSlcblxuY29uc3QgQ29udGFpbmVyID0gc3R5bGVkKCdidXR0b24nKWBcbiAgJHtzdHlsZXNJbkNhbGxiYWNrfVxuICAkeygpID0+XG4gICAgY3NzKHtcbiAgICAgIGJhY2tncm91bmQ6ICdyZWQnLFxuICAgIH0pfVxuYFxuZXhwb3J0IGNsYXNzIFNpbXBsZUNvbXBvbmVudCBleHRlbmRzIFB1cmVDb21wb25lbnQge1xuICByZW5kZXIoKSB7XG4gICAgcmV0dXJuIChcbiAgICAgIDxDb250YWluZXI+XG4gICAgICAgIDxzcGFuPmhlbGxvPC9zcGFuPlxuICAgICAgPC9Db250YWluZXI+XG4gICAgKVxuICB9XG59XG5cblJlYWN0RE9NLnJlbmRlcig8U2ltcGxlQ29tcG9uZW50IC8+LCBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCcjYXBwJykpXG4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBaUJxQiJ9 */'
+)
const SpanContainer = styled('span', {
target: 'ep3ww291',
- label: 'label:SpanContainer',
-})({
- background: 'yellow',
-})
+ label: 'SpanContainer',
+})(
+ {
+ background: 'yellow',
+ },
+ '/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiL1VzZXJzL2xvbmd5aW5hbi93b3Jrc3BhY2UvZ2l0aHViL25leHQuanMvcGFja2FnZXMvbmV4dC1zd2MvY3JhdGVzL2NvcmUvdGVzdHMvZml4dHVyZS9lbW90aW9uL2Nzcy1pbi1jYWxsYmFjay9pbnB1dC50c3giLCJzb3VyY2VzIjpbIi9Vc2Vycy9sb25neWluYW4vd29ya3NwYWNlL2dpdGh1Yi9uZXh0LmpzL3BhY2thZ2VzL25leHQtc3djL2NyYXRlcy9jb3JlL3Rlc3RzL2ZpeHR1cmUvZW1vdGlvbi9jc3MtaW4tY2FsbGJhY2svaW5wdXQudHN4Il0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGNzcyB9IGZyb20gJ0BlbW90aW9uL3JlYWN0J1xuaW1wb3J0IHN0eWxlZCBmcm9tICdAZW1vdGlvbi9zdHlsZWQnXG5pbXBvcnQgeyBQdXJlQ29tcG9uZW50IH0gZnJvbSAncmVhY3QnXG5pbXBvcnQgUmVhY3RET00gZnJvbSAncmVhY3QtZG9tJ1xuXG5jb25zdCBzdHlsZXNJbkNhbGxiYWNrID0gKHByb3BzOiBhbnkpID0+XG4gIGNzcyh7XG4gICAgY29sb3I6ICdyZWQnLFxuICAgIGJhY2tncm91bmQ6ICd5ZWxsb3cnLFxuICAgIHdpZHRoOiBgJHtwcm9wcy5zY2FsZSAqIDEwMH1weGAsXG4gIH0pXG5cbmNvbnN0IHN0eWxlcyA9IGNzcyh7XG4gIGNvbG9yOiAncmVkJyxcbiAgd2lkdGg6ICcyMHB4Jyxcbn0pXG5cbmNvbnN0IERpY0NvbnRhaW5lciA9IHN0eWxlZC5kaXYoe1xuICBiYWNrZ3JvdW5kOiAncmVkJyxcbn0pXG5cbmNvbnN0IFNwYW5Db250YWluZXIgPSBzdHlsZWQoJ3NwYW4nKSh7XG4gIGJhY2tncm91bmQ6ICd5ZWxsb3cnLFxufSlcblxuY29uc3QgQ29udGFpbmVyID0gc3R5bGVkKCdidXR0b24nKWBcbiAgJHtzdHlsZXNJbkNhbGxiYWNrfVxuICAkeygpID0+XG4gICAgY3NzKHtcbiAgICAgIGJhY2tncm91bmQ6ICdyZWQnLFxuICAgIH0pfVxuYFxuZXhwb3J0IGNsYXNzIFNpbXBsZUNvbXBvbmVudCBleHRlbmRzIFB1cmVDb21wb25lbnQge1xuICByZW5kZXIoKSB7XG4gICAgcmV0dXJuIChcbiAgICAgIDxDb250YWluZXI+XG4gICAgICAgIDxzcGFuPmhlbGxvPC9zcGFuPlxuICAgICAgPC9Db250YWluZXI+XG4gICAgKVxuICB9XG59XG5cblJlYWN0RE9NLnJlbmRlcig8U2ltcGxlQ29tcG9uZW50IC8+LCBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCcjYXBwJykpXG4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBcUJzQiJ9 */'
+)
const Container = styled('button')`
${stylesInCallback}
${() =>
@@ -38,7 +46,8 @@ const Container = styled('button')`
{
background: 'red',
},
- 'label:Container'
+ 'label:Container',
+ '/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiL1VzZXJzL2xvbmd5aW5hbi93b3Jrc3BhY2UvZ2l0aHViL25leHQuanMvcGFja2FnZXMvbmV4dC1zd2MvY3JhdGVzL2NvcmUvdGVzdHMvZml4dHVyZS9lbW90aW9uL2Nzcy1pbi1jYWxsYmFjay9pbnB1dC50c3giLCJzb3VyY2VzIjpbIi9Vc2Vycy9sb25neWluYW4vd29ya3NwYWNlL2dpdGh1Yi9uZXh0LmpzL3BhY2thZ2VzL25leHQtc3djL2NyYXRlcy9jb3JlL3Rlc3RzL2ZpeHR1cmUvZW1vdGlvbi9jc3MtaW4tY2FsbGJhY2svaW5wdXQudHN4Il0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGNzcyB9IGZyb20gJ0BlbW90aW9uL3JlYWN0J1xuaW1wb3J0IHN0eWxlZCBmcm9tICdAZW1vdGlvbi9zdHlsZWQnXG5pbXBvcnQgeyBQdXJlQ29tcG9uZW50IH0gZnJvbSAncmVhY3QnXG5pbXBvcnQgUmVhY3RET00gZnJvbSAncmVhY3QtZG9tJ1xuXG5jb25zdCBzdHlsZXNJbkNhbGxiYWNrID0gKHByb3BzOiBhbnkpID0+XG4gIGNzcyh7XG4gICAgY29sb3I6ICdyZWQnLFxuICAgIGJhY2tncm91bmQ6ICd5ZWxsb3cnLFxuICAgIHdpZHRoOiBgJHtwcm9wcy5zY2FsZSAqIDEwMH1weGAsXG4gIH0pXG5cbmNvbnN0IHN0eWxlcyA9IGNzcyh7XG4gIGNvbG9yOiAncmVkJyxcbiAgd2lkdGg6ICcyMHB4Jyxcbn0pXG5cbmNvbnN0IERpY0NvbnRhaW5lciA9IHN0eWxlZC5kaXYoe1xuICBiYWNrZ3JvdW5kOiAncmVkJyxcbn0pXG5cbmNvbnN0IFNwYW5Db250YWluZXIgPSBzdHlsZWQoJ3NwYW4nKSh7XG4gIGJhY2tncm91bmQ6ICd5ZWxsb3cnLFxufSlcblxuY29uc3QgQ29udGFpbmVyID0gc3R5bGVkKCdidXR0b24nKWBcbiAgJHtzdHlsZXNJbkNhbGxiYWNrfVxuICAkeygpID0+XG4gICAgY3NzKHtcbiAgICAgIGJhY2tncm91bmQ6ICdyZWQnLFxuICAgIH0pfVxuYFxuZXhwb3J0IGNsYXNzIFNpbXBsZUNvbXBvbmVudCBleHRlbmRzIFB1cmVDb21wb25lbnQge1xuICByZW5kZXIoKSB7XG4gICAgcmV0dXJuIChcbiAgICAgIDxDb250YWluZXI+XG4gICAgICAgIDxzcGFuPmhlbGxvPC9zcGFuPlxuICAgICAgPC9Db250YWluZXI+XG4gICAgKVxuICB9XG59XG5cblJlYWN0RE9NLnJlbmRlcig8U2ltcGxlQ29tcG9uZW50IC8+LCBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCcjYXBwJykpXG4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBNEJJIn0= */'
)}
`
export class SimpleComponent extends PureComponent {
diff --git a/packages/next/build/swc/options.js b/packages/next/build/swc/options.js
index 2d2cbee22fa8b..339f550513ce5 100644
--- a/packages/next/build/swc/options.js
+++ b/packages/next/build/swc/options.js
@@ -52,7 +52,9 @@ export function getBaseSWCOptions({
legacyDecorator: enableDecorators,
decoratorMetadata: emitDecoratorMetadata,
react: {
- importSource: jsConfig?.compilerOptions?.jsxImportSource || 'react',
+ importSource: nextConfig?.emotion?.enabled
+ ? '@emotion/react'
+ : jsConfig?.compilerOptions?.jsxImportSource || 'react',
runtime: 'automatic',
pragma: 'React.createElement',
pragmaFrag: 'React.Fragment',
@@ -89,6 +91,37 @@ export function getBaseSWCOptions({
removeConsole: nextConfig?.compiler?.removeConsole,
reactRemoveProperties: nextConfig?.compiler?.reactRemoveProperties,
relay: nextConfig?.compiler?.relay,
+ emotion: getEmotionOptions(nextConfig, development),
+ }
+}
+
+function getEmotionOptions(nextConfig, development) {
+ if (
+ !nextConfig?.compiler?.emotion ||
+ !nextConfig?.compiler?.emotion?.enabled
+ ) {
+ return null
+ }
+ let autoLabel = false
+ switch (nextConfig?.compiler?.emotion?.autoLabel) {
+ case 'never':
+ autoLabel = false
+ break
+ case 'always':
+ autoLabel = true
+ break
+ case 'dev-only':
+ default:
+ autoLabel = !!development
+ break
+ }
+ return {
+ enabled: true,
+ autoLabel,
+ labelFormat: nextConfig?.compiler?.emotion?.labelFormat,
+ sourcemap: development
+ ? nextConfig?.compiler?.emotion?.sourceMap ?? true
+ : false,
}
}
diff --git a/packages/next/build/webpack-config.ts b/packages/next/build/webpack-config.ts
index 82d9cb2d9e609..5dfad38af146b 100644
--- a/packages/next/build/webpack-config.ts
+++ b/packages/next/build/webpack-config.ts
@@ -1633,6 +1633,7 @@ export default async function getBaseWebpackConfig(
reactRemoveProperties: config.compiler?.reactRemoveProperties,
styledComponents: config.compiler?.styledComponents,
relay: config.compiler?.relay,
+ emotion: config.compiler?.emotion,
})
const cache: any = {
diff --git a/packages/next/server/config-shared.ts b/packages/next/server/config-shared.ts
index b927e37ffdc81..840cb175edb70 100644
--- a/packages/next/server/config-shared.ts
+++ b/packages/next/server/config-shared.ts
@@ -382,6 +382,12 @@ export interface NextConfig extends Record {
exclude?: string[]
}
styledComponents?: boolean
+ emotion?: {
+ enabled?: boolean
+ sourceMap?: boolean
+ autoLabel?: 'dev-only' | 'always' | 'never'
+ labelFormat?: string
+ }
}
/**