Closed4

Linaria Setupメモ(React / TypeScript)

mori5321mori5321

TypeScriptでの構築方法のドキュメント&文献が少ないのでメモ。

Linaria系のライブラリをインストール

npm install -S @linaria/babel-preset @linaria/core @linaria/react @linaria/shaker

babel系のライブラリをインストール

npm install -D @babel/core @babel/preset-env @babel/preset-typescript

loader系のライブラリをインストール

npm install -D babel-loader @linaria/webpack-loader ts-loader css-loader

css系のpluginをインストール

npm install -S mini-css-extract-plugin
npm install -D @types/mini-css-extract-plugin
mori5321mori5321

Linariaは現状 babelが必須なので、

  • TypeScriptの型チェック -> ts-loaderにやらせる
  • Linaria用の処理 & ES5へのトランスパイル -> Babelにやらせる

という形式をとる。
loaderは後ろから順番に実行されるため、順序に注意。
ts-loader -> babel-loaderの順に実行したいため、babel-loader, ts-loaderの順で記載する。

※とりあえず問題なくLinariaは動きますが、babelとlinariaの設定の部分はちょっと自信ないので怪しい点あったらご指摘ください。

webpack.config.common.ts

import * as path from "path"
import {Configuration} from "webpack";
import * as devServer from "webpack-dev-server";
import MiniCssExtractPlugin from "mini-css-extract-plugin";

export type WebpackConfig = Configuration & { devServer?: devServer.Configuration }

export const commonConfig: WebpackConfig  = {
  mode: "development",
  devtool: "inline-source-map",
  context: path.join(__dirname, "src"),
  entry: "./index.tsx",
  output: {
    path: path.join(__dirname, "dist"),
    filename: "bundle.js",
  },
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        use: [
          {loader: 'babel-loader'},
          {
            loader: '@linaria/webpack-loader',
            options: {
              sourceMap: process.env.NODE_ENV !== 'production'
            }
          },
          { loader: 'ts-loader' }
        ],
      },
      {
        test: /\.css$/,
        use: [
          { loader: MiniCssExtractPlugin.loader },
          {
            loader: 'css-loader',
            options: {
              sourceMap: process.env.NODE_ENV !== 'production'
            }
          }
        ]
      }
    ],
  },
  resolve: {
    extensions: [".ts", ".tsx", ".js", ".jsx"],
    alias: {
      "@": path.resolve(__dirname, "src"),
      "assets": path.resolve(__dirname, "assets"),
    }
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: 'styles.css',
    })
  ]
}

webpack.config.dev.ts

import {commonConfig} from './webpack.config.common';
import {merge} from 'webpack-merge';
import * as path from "path"
import { WebpackConfig } from './webpack.config.common'

const devConfig: WebpackConfig = merge(commonConfig, {
  mode: 'development',
  devtool: 'inline-source-map',
  devServer: {
    port: 8080,
    contentBase: path.join(__dirname, "dist")
  }
})

export default devConfig;

babelrc

{
  "presets": [
        "@babel/preset-env",
        "@babel/preset-react",
        "@linaria"
  ],
}

tsconfig.json(ts-loader用)

{
  "compilerOptions": {
    "typeRoots": ["types", "node_modules/@types"],
    "sourceMap": true,
    "target": "esnext", // babelでES5にトランスパイルするためtsconfigではesnextにする。ここをES5などにするとLinariaが動かないので注意。
    "module": "esnext", 
    "jsx": "react",
    "moduleResolution": "node",
    "lib": ["es2020", "dom"],
    "baseUrl": "./",
    "paths": {
      "@/*": ["./src/*"]
    },
    "esModuleInterop": true,
    "allowJs": false,
    "allowUnreachableCode": false,
    "allowUnusedLabels": false,
    "alwaysStrict": true,
    "noImplicitAny": true,
    "noImplicitReturns": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "strictNullChecks": true,
    "skipLibCheck": true,
    "strict": false,
    "forceConsistentCasingInFileNames": true,
    "resolveJsonModule": true
  },
  "include": ["src/**/*.ts", "src/**/*.tsx"],
  "exclude": ["node_modules"]
}
mori5321mori5321

index.htmlのheadタグ内に以下をimport

<link rel="stylesheet" href="/styles.css" type="text/css" />
mori5321mori5321

適当に css 関数を使ってStyleを定義してあげると、/.linaria-cache 配下にcssが吐かれておりスタイリング成功。完。

import * as React from "react";
import * as ReactDOM from "react-dom";

import { css } from "@linaria/core";

const App: React.VFC = () => {
  return (
    <div className={sampleStyle}>
      <h1>HelloWorld</h1>
    </div>
  );
};

const sampleStyle = css`
  color: red;
`;

ReactDOM.render(<App />, document.getElementById("app"));
このスクラップは2ヶ月前にクローズされました