TypeScript e React ou Next: Importando uma lib em TypeScript no contexto de um monorepo sem transpilar para JavaScript

Primeiro, precisamos entender o contexto ao qualfacto desenvolver esse texto. Suponhamos que você tenha um monorepo (nesse caso, em específico, usando o yarn workspaces ) com um projeto em React (criado utilizando o create-react-app ) e um projeto de um sdk com chamadas para uma api qualquer, feito em TypeScript. O Objetivo principal é: importar o pacote sdk no app React sem a necessidade de transpilar/compilar o projeto sdk em toda alteração.

부인 성명



Esse é um texto escrito com uma motivação em específica: quando precisioni fazer isso não encontrei nenhum material parecido e isso acabou me custando algum tempo de pesquisa e, portanto, resolvi deixar a solução encontrada registrada.

Estrutura do Projeto



Como já mencionado no primeiro parágrafo, a estrutura do projeto, utilizando o yarn workspaces 기본 사항:



SDK



O pacote sdk contém apenas um arquivo index.ts com uma função que faz uma requisição para uma api pública(예시):

import axios from 'axios';

export interface CatImageItem {
    id: number;
    url: string;
    webpurl: string;
    x: number;
    y: number;
}

export async function getCat(): Promise<CatImageItem> {
    const result = await axios.get<CatImageItem>('https://thatcopy.pw/catapi/rest/');
    return result.data;
}


Com o package.json :

{
  "name": "@monorepo/sdk",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "devDependencies": {
    "typescript": "^4.4.4"
  },
  "dependencies": {
    "axios": "^0.24.0"
  }
}


내 앱



Já o app em react é, somente, uma chamada do método exportado pelo sdk de exemplo:

import React, { useEffect, useState } from 'react';
import { getCat, CatImageItem } from '@monorepo/sdk';

function App() {
    const [cat, setCat] = useState<CatImageItem | null>(null);

    useEffect(() => {
        async function fetchCat() {
            const cat = await getCat();
            setCat(cat);
        }
        fetchCat();
    }, []);

    return (
        <div className="App">
            <h1>My Cat</h1>
            {cat && (
                <img src={cat.url} style={{ maxWidth: 400 }} />
            )}
        </div>
    );
}

export default App;


오 문제



Ao tentar rodar o projeto com os itens acima, obtemos de cara o erro:



Olhando para owebpack.config.js do create-react-app, onde é definido a regra do webpack para utilizar o babel para processor os arquivos TypeScript (aqui ), possui a propriedade include que garante que só os arquivos dentro do app sejam processados ​​por aquela regra, então o que acontece é que o nosso pacote simplesmente não é processado:

{
    test: /\.(js|mjs|jsx|ts|tsx)$/,
    include: paths.appSrc,
    loader: require.resolve('babel-loader'),
    // ...


해결책



Existem duas soluções básicas: a primeira é ejetar o app, porém não quero entrar nessa pois é um tanto quanto trabalhosa. A segunda é utilizar o pacote react-app-rewired para rodar o nosso app e, portanto, poder reconfigurarar o webpack. Então, primeiro, vamos instalar or pacote:

yarn workspace @monorepo/my-app add -D react-app-rewired


번호 package.json my-app precisamos alterar alguns 스크립트 파라:

{
  //...
  "scripts": {
    "start": "react-app-rewired start",
    "build": "react-app-rewired build",
    "test": "react-app-rewired test",
    "eject": "react-scripts eject"
  },
  //...
}


아고라, precisamos criar um arquivo config-overrides.js my-app 프로젝트를 시작하려면 vamos remover aquele에 TypeScript seja processado pelo nosso projeto를 포함하십시오.

module.exports = {
    webpack: function(config, env) {
        config.module.rules[1].oneOf[2].include = undefined;
        return config;
    }
};


웹팩을 구성할 때 acima vai sobreescrever는 webpack, alterando, na segunda regra de module, o terceiro item do array oneOf, mudando o include para undefined, ou seja, dizendo que o include não estará mais presente ali.

Agora, ao rodar o projeto, obtemos o nosso gatinho, sem nenhum erro:



O repositório pode ser acessado clicando aqui .

수정: Next.JS가 없나요?



No NextJS é um pouco mais simples pois não é necessário instalar nada. Basta no arquivo next.config.js 구성 변수 또는 매개 변수: webpack adicionando o caminho para o pacote que deseja importar da seguinte 형식:

const path = require('path');

/** @type {import('next').NextConfig} */
module.exports = {
  //...
  webpack: (config, { buildId, dev, isServer, defaultLoaders, webpack }) => {
    // Important: return the modified config
    config.module.rules[2].oneOf[0].include.push(
      path.resolve(
        __dirname, '..', 'sdk',
      ),
    );
    return config;
  },
}


path.resolve irá retornar o caminho absoluto para o caminho do pacote sdk.

좋은 웹페이지 즐겨찾기