2020.9.12
Reactの軽量版という立ち位置のPreactでEmotionを使おうとして少しハマったので備忘録として書き残します。
Fast 3kB alternative to React with the same modern API
Preactは上記のように書かれているのでライブラリとしてはかなり軽量な部類に入るのではないでしょうか。バンドルサイズを軽くしたいときはReactではなくこちらを使うと良いかと思います。今回もその理由でPreactを採用しました。
React × TypeScript 環境でEmotionを使うのは以下を参考にすれば良かったです。
Preact × Webpack × TypeScriptのプロジェクトを作っていきます。
yarn add @emotion/core @emotion/styled preact
yarn add -D @types/react ts-loader tslint typescript webpack webpack-cli webpack-dev-server
./node_modules/.bin/tsc --init
ディレクトリはこんな感じです。
$ tree -I node_modules
.
├── build
│ └── index.html
├── package.json
├── src
│ └── index.tsx
├── tsconfig.json
├── webpack.config.js
└── yarn.lock
src/index.tsx
はこのようにしました。
import { h, render } from "preact";
const App = () => {
return <div>Hello Preact Emotion!</div>
};
render(<App />, document.getElementById("app") as Element);
React × Webpack × TypeScriptの雛形はこちらに置いてあります。ほぼこちらの雛形通りです。
sandbox/webpack-react-typescript at master · SatoshiKawabata/sandbox · GitHub
JSXがTypeScriptで認識されていないエラーが出たのでtsconfig.json
に設定を追加します。
ERROR in ./src/index.tsx 5:11
Module parse failed: Unexpected token (5:11)
File was processed with these loaders:
* ./node_modules/ts-loader/index.js
You may need an additional loader to handle the result of these loaders.
| var preact_1 = require("preact");
| var App = function () {
> return <div>Hello Preact Emotion!</div>;
| };
| preact_1.render(<App />, document.getElementById("app"));
ERROR in /src/index.tsx
./src/index.tsx
[tsl] ERROR in /src/index.tsx(4,10)
TS17004: Cannot use JSX unless the '--jsx' flag is provided.
ERROR in /src/index.tsx
./src/index.tsx
[tsl] ERROR in /src/index.tsx(7,8)
TS17004: Cannot use JSX unless the '--jsx' flag is provided.
ℹ 「wdm」: Failed to compile.
tsconfig.json
に下記を追記してJSXを認識させます。Preactはh
関数を使うためjsxFactory
をh
に設定しています。
"compilerOptions": {
"jsx": "react",
"jsxFactory": "h",
}
Emotionを追加するためにindex.tsx
に下記のようにします。@emotion/core
を使おうと思ったのですが、JSXの認識がうまくいかなかったので@emotion/styled
を使います。
import { h, render } from "preact";
import styled from "@emotion/styled";
const SomeComp = styled.h1`
color: hotpink;
`;
const App = () => {
return <SomeComp>Hello Preact Emotion!</SomeComp>
};
render(<App />, document.getElementById("app") as Element);
Module not found: Error: Can't resolve 'react' in '/node_modules/@emotion/core/dist'
エラーが出たEmotion内でReactを使っているらしく下記のエラーが出ました。
ERROR in ./node_modules/@emotion/core/dist/core.browser.esm.js
Module not found: Error: Can't resolve 'react' in '/node_modules/@emotion/core/dist'
@ ./node_modules/@emotion/core/dist/core.browser.esm.js 2:0-76 10:26-39 17:19-32 22:11-24 28:9-19 82:12-25 92:11-24 110:11-24 156:9-22 175:11-24 177:13-26 185:9-22 257:2-11 332:9-22
@ ./node_modules/@emotion/styled-base/dist/styled-base.browser.esm.js
@ ./node_modules/@emotion/styled/dist/styled.browser.esm.js
@ ./src/worker/WorkerLogin.tsx
@ ./src/login.tsx
ERROR in ./node_modules/@emotion/styled-base/dist/styled-base.browser.esm.js
Module not found: Error: Can't resolve 'react' in '/node_modules/@emotion/styled-base/dist'
@ ./node_modules/@emotion/styled-base/dist/styled-base.browser.esm.js 2:0-38 85:13-26 134:18-31
@ ./node_modules/@emotion/styled/dist/styled.browser.esm.js
@ ./src/worker/WorkerLogin.tsx
@ ./src/login.tsx
ℹ 「wdm」: Failed to compile.
PreactにはReactとの互換性を保つためのモジュールがあるようで、そちらをWebpackのaliasとして使うように変更しました。
Preact X, Preact render to string & Styled Components · Issue #1417 · preactjs/preact · GitHub
こちらにも詳しく書かれているみたいです。
resolve: {
alias: {
react: 'preact/compat',
}
}
これで動くと思います。
今回のプロジェクトはこちらに置いておきました。
sandbox/webpack-prect-typescript-emotion at master · SatoshiKawabata/sandbox · GitHub
Emotion関連ではこちらの記事も書いていますのでよかったら覗いてください。