Preact 使う
Alias でやる作戦
webpack や jest で react の alias として使う設定例がある
楽したいわけでもないし、まず素直に使えるようにしてみる
import
普段使うやつどこにあるか
code:import.ts
import {h, render, createContext, Fragment, VNode} from 'preact';
import {useState, useEffect, useContext, useCallback useRef, useReducer} from 'preact/hooks';
import {memo} from 'preact/compat';
import type {ComponentChildren} from 'preact';
jsxFactory
'React' refers to a UMD global, but the current file is a module. Consider adding an import instead.ts(2686)
コードに import {h} from 'preact'; を追加
tsconfig.json
compilerOptions に "jsxFactory": "h" を設定する
デフォルトは React.createElement なので JSX を変換する際スコープに React が必要
2021/6/26 TypeScript >= 4.1.1 では以下の設定に
React の eslint 設定が残っていると怒られるので
eslint-plugin-react は普通に使う
"react/react-in-jsx-scope": "off"
settings.react.pragma を "h" にする
これで h の no-unused-vars も消える
settings.react.fragment も "Fragment" にするとよい
? h である必要あるかな?
Preact は createElement もあるので import React, {...} from 'preact' とかのが楽だったりしないかな?
実際どうなのか、型とか合うのかは見てない
? Warning: React version was set to "detect" in eslint-plugin-react settings, but the "react" package is not installed. Assuming latest React version for linting.
settings.react.version が "detect" なら react がないと言われるし、消せば書けと言われる
"latest" とすると黙るけどウソじゃん
Fragment
jsxFactory を指定している時 <>...</> の JSX fragment は使えない
import { Fragment } from 'preact'; があるので代わりに使う
<Fragment>...</Fragment>
TypeScript 4.0 で jsxFragmentFactory が compilerOptions に入る
tsconfig.json で "jsxFragmentFactory": "Fragment" を指定するとよい
VNode
たぶん ReactNode の代わり
イベントの型が合わない
Context
createContext は preact
useContext は preact/hooks
styled-component
react 一式を削除して build した際に出た
code:styled-component.error
ERROR in ./node_modules/styled-components/dist/styled-components.browser.esm.js
Module not found: Error: Can't resolve 'react' in '/Users/pokutuna/.ghq/github.com/pokutuna/chrome-cocopy/node_modules/styled-components/dist'
styled-components が React を参照している
うーん結局 alias しないといけなさそう
code:webpack.config.js
resolve: {
alias: {
react: 'preact/compat',
'react-dom/test-utils': 'preact/test-utils',
'react-dom': 'preact/compat',
},
},
...
jsx-runtime 対応
preact では
jest では alias する
code:jest.config.js
module.exports = {
preset: 'ts-jest',
testEnvironment: 'jsdom',
moduleNameMapper: {
'^react$': 'preact/compat',
'^react-dom$': 'preact/compat',
'^react-dom/test-utils$': 'preact/test-utils',
'^react/jsx-runtime$': 'preact-jsx-runtime',
},
};
test & lint
eslint-config-preact
なんか強いな、plugin とかじゃない、gts や ts と組み合せられなさそうだし使わない install せず index.js 見て必要なところだけ真似ようかと思ったけど、そんなにないかな
(普通に React として lint とかを設定してればだいたいよさそう)
jest-preset-preact
まだみてない、テスト中の JSX を preact の h にしてくれそう
みた
ts-jest と同時に使うのだるいので必要なところ(モジュール名のマッピング)だけ参考にする
code:jest.config.js
module.exports = {
...
moduleNameMapper: {
'^react$': 'preact/compat',
'^react-dom$': 'preact/compat',
'^.+\\.(css|sass|scss|less)$': 'identity-obj-proxy',
},
};
preact-render-to-string
snapshot テストするときに
デフォルトは pretty な出力じゃなくて diff がまともに見れないのでオプションを渡す
code:App.test.tsx
import {h} from 'preact';
import render from 'preact-render-to-string';
import {App} from './App';
test('render App', () => {
expect(render(<App />, {}, {pretty: true})).toMatchSnapshot();
});
非同期に取得する値とか待ってくれない?
2020/12/21 使ってない
@testing-library/pract
これぐらいでなんとかなっている
code:imports
import {render, screen, waitFor} from '@testing-library/preact';
import '@testing-library/jest-dom';
import 'jest-styled-components';
---.icon
サイズ差
スカスカのブラウザ拡張でみてみる
React
code:build-react
$ webpack
Hash: 63ac109e35f56a48c91f
Version: webpack 4.43.0
Time: 3849ms
Built at: 2020-07-16 10:11:08
Asset Size Chunks Chunk Names
eventpage.js 22.1 KiB eventpage emitted eventpage options.js 2.63 MiB options emitted options popup.js 2.38 MiB popup emitted popup sandbox.js 12.4 KiB sandbox emitted sandbox Entrypoint eventpage = eventpage.js
Entrypoint sandbox = sandbox.js
Entrypoint popup = popup.js
Entrypoint options = options.js
+ 23 hidden modules
Preact
code:build-preact
$ webpack
Hash: 39688f882396dc42a4a8
Version: webpack 4.43.0
Time: 2955ms
Built at: 2020-07-16 10:10:38
Asset Size Chunks Chunk Names
eventpage.js 22.1 KiB eventpage emitted eventpage options.js 518 KiB options emitted options popup.js 63.5 KiB popup emitted popup sandbox.js 12.4 KiB sandbox emitted sandbox Entrypoint eventpage = eventpage.js
Entrypoint sandbox = sandbox.js
Entrypoint popup = popup.js
Entrypoint options = options.js
+ 20 hidden modules
見づらいので差
code:js-sizes-with-react
eventpage.js 22.1 KiB eventpage emitted eventpage options.js 2.63 MiB options emitted options popup.js 2.38 MiB popup emitted popup sandbox.js 12.4 KiB sandbox emitted sandbox code:js-sizes-with-preact
eventpage.js 22.1 KiB eventpage emitted eventpage options.js 346 KiB options emitted options popup.js 63.5 KiB popup emitted popup sandbox.js 12.4 KiB sandbox emitted sandbox sanbox や eventpage は react 使ってないので差が出てない