【问题标题】:Importing JavaScript to TypeScript app with Lerna使用 Lerna 将 JavaScript 导入 TypeScript 应用程序
【发布时间】:2020-07-16 13:31:55
【问题描述】:

我尝试用 2 个 React 包创建一个 monorepo:

  • TypeScript (npx create-react-app app --template typescript)
  • JavaScript (ui)

我有一个基本的lerna.json 配置

{
  "packages": ["packages/*"],
  "version": "1.0.0"
}

ui 包中,我只需导出一个按钮(来自src/Button.jsx):

import React from 'react';

const Button = () => {
  return (
    <button>
      Start
    </button>
  )
}

export default Button;

我已经引导 app 使用 ui 包。 在app 中导入它会导致以下错误:

Failed to compile
/lerna-demo/packages/ui/src/Button.jsx 5:4
Module parse failed: Unexpected token (5:4)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
| const Button = () => {
|   return (
>     <button>
|       Start
|     </button>

有没有办法将加载程序添加到 lerna 或 app 以修复导入?

编辑

项目结构:

lerna-demo/
  - node_modules/
  - lerna.json
  - package.json
  - packages/
    - app (created using create-react-app)
      - ...
    - ui
      - node_modules/
      - package.json
      - yarn.lock
      - src/
        - Button.jsx

我导入Button组件的方式:

import React from 'react';
import logo from './logo.svg';
import './App.css';
import * as Button from 'ui/src/Button';

const App: React.FC = () => {

  return (
    <div className="App">
      <Button />
    </div>
  );
}

export default App;

【问题讨论】:

标签: javascript reactjs typescript lerna


【解决方案1】:

在您由 CRA 创建的 tsconfig.json 中,您需要告诉编译器还包含 ui pacakge,因此在您的示例中是这样的:

{
  "compilerOptions": {
    "target": "es5",
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ],
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react"
  },
  "include": [
    "src", "../ui/src",
  ]
}

另一种选择是扩展您的基本 lerna tsconfig.json,我猜它已经用 path 指向您的包 - 所以从您的 CRA tsconfig.json 只需添加以下内容:

{
    "extends": "../../tsconfig.json",

在基础tsconfig.json 中,您应该定义路径的别名: 主tsconfig.json

{
    "compilerOptions": {
        "baseUrl": "./",
        "paths": {
            "ui/*": ["./packages/ui/*"],

【讨论】:

  • 我的情况与问题中的情况完全相同。在基本 tsconfig 中添加 paths 或包含在包 tslint 中不起作用。我有时只能看到错误消息的变化。似乎 CRA 的开发人员不希望您能够做到这一点。将出现一条错误消息:The following changes are being made to your tsconfig.json file: - compilerOptions.paths must not be set (aliased imports are not supported) 我认为人们已经面临同样的问题并正在寻找解决方法。到目前为止,我还没有找到神奇的调整,但会回来的。
【解决方案2】:

我关注了this answer,并能够通过使用craco 并将webpack 配置指向我的独立包,将我的lerna monorepo 中的单独独立包导入我的CRA typescript 应用程序。我发现此解决方案更易于管理,而不是从您现有的 CRA 配置中弹出。

鉴于此结构:

├── package.json
├── packages
│   ├── app
│   ├── ui
└── yarn.lock

...这里是主要步骤:

  1. app/package.json中安装craco
yarn add @craco/craco
  1. 在 CRA 项目根目录中创建 craco.config.js 文件
├── package.json
├── packages
│   ├── app
│   │   ├── src
│   │   └── craco.config.json <--- in CRA project root
│   │  
│   ├── ui
│   │   ├── src
│   
│   
└── yarn.lock
  1. 将 webpack 配置指向共享模块
// project/app/craco.config.js
// ---
const path = require('path');
/**
 * ALlows us to edit create-react-app configuration
 * without ejecting.
 *
 *
 */
const { getLoader, loaderByName } = require('@craco/craco');
// Replace `components` with your folder's structure.
// Again, Here I'm showcasing my current project.
const absolutePath = path.join(__dirname, '../ui');
/**
 * This is extremely important if you're using a CI/CD to build and deploy 
 * your code!!! Read!
 * 
 * If you create a package with a namespace, such as name is @schon/components, you need
 * to add what I've commented down below. Otherwise Yarn will fail in CI/CD environments!!
 */
// const uiComponents = path.join(
//   __dirname,
//   './node_modules/ui',
// );

module.exports = {
  webpack: {
    configure: (webpackConfig, { env, paths }) => {
      // https://medium.com/frontend-digest/using-create-react-app-in-a-monorepo-a4e6f25be7aa
      const { isFound, match } = getLoader(
        webpackConfig,
        loaderByName('babel-loader'),
      );
      if (isFound) {
        const include = Array.isArray(match.loader.include)
          ? match.loader.include
          : [match.loader.include];
        // match.loader.include = include.concat(absolutePath, uiComponents);
        match.loader.include = include.concat(absolutePath);
      }
      return {
        ...webpackConfig,
        /**
         * Optionally, other webpack configuration details.
         */
        // optimization: {
        //   splitChunks: {
        //   },
        // },
      };
    },
  },
  
};

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-06-11
    • 2019-04-21
    • 2017-05-23
    • 2018-03-21
    • 1970-01-01
    • 2018-11-14
    • 1970-01-01
    • 2020-02-28
    相关资源
    最近更新 更多