Перенос приложения Create React (Webpack) в NX и искажение Vite — URI при decodeURI

#typescript #monorepo #vite

#typescript #monorepo #vite

Вопрос:

Это будет непросто, потому что здесь многое происходит. Поэтому я постараюсь быть как можно более кратким, чтобы не перегружать вас слишком большим количеством информации.

В настоящее время я нахожусь в процессе удаления монореактивного приложения Create React приличного размера, управляемого с помощью Bolt Package Manager и Yarn, в монореактивный модуль nx, управляемый с помощью Vite.

Я создал пустой проект и начал перемещать проекты один за другим. Мне удалось успешно перенести проект сборника рассказов (Webpack), но не основное приложение, которое я пытаюсь запустить в Vite:

В настоящее время я столкнулся с проблемой неправильной формы decodeURI. Я понятия не имею, что это вызывает.

 C:UsersasiliDocumentsProgrammingschonnode_modulesvitedistnodechunksdep-3daf770c.js:57562
        let url = decodeURI(removeTimestampQuery(req.url)).replace(NULL_BYTE_PLACEHOLDER, '');
URIError: URI malformed
    at decodeURI (<anonymous>)
    at viteTransformMiddleware (C:UsersasiliDocumentsProgrammingschonnode_modulesvitedistnodechunksdep-3daf770c.js:57562:19)
    at call (C:UsersasiliDocumentsProgrammingschonnode_modulesvitedistnodechunksdep-3daf770c.js:46063:7)
    at next (C:UsersasiliDocumentsProgrammingschonnode_modulesvitedistnodechunksdep-3daf770c.js:46007:5)
    at C:UsersasiliDocumentsProgrammingschonnode_modulesvitedistnodechunksdep-3daf770c.js:57212:28
    at viteServePublicMiddleware (C:UsersasiliDocumentsProgrammingschonnode_modulesvitedistnodechunksdep-3daf770c.js:57251:9)
    at call (C:UsersasiliDocumentsProgrammingschonnode_modulesvitedistnodechunksdep-3daf770c.js:46063:7)
    at next (C:UsersasiliDocumentsProgrammingschonnode_modulesvitedistnodechunksdep-3daf770c.js:46007:5)
    at next (C:UsersasiliDocumentsProgrammingschonnode_modulesvitedistnodechunksdep-3daf770c.js:45985:14)
    at next (C:UsersasiliDocumentsProgrammingschonnode_modulesvitedistnodechunksdep-3daf770c.js:45985:14)

 

Вот мой package.json:

 {
  "name": "schon",
  "version": "0.0.0",
  "license": "MIT",
  "scripts": {
    "start": "nx serve",
    "build": "nx build",
    "test": "nx test"
  },
  "private": true,
  "dependencies": {
    "@apollo/client": "^3.5.6",
    "@auth0/auth0-react": "^1.8.0",
    "@aws-sdk/client-s3": "^3.44.0",
    "@date-io/date-fns": "^2.11.0",
    "@material-table/core": "^4.3.11",
    "@material-ui/core": "^4.12.3",
    "@material-ui/icons": "^4.11.2",
    "@material-ui/lab": "^4.0.0-alpha.60",
    "@material-ui/pickers": "^3.3.10",
    "@material-ui/system": "^4.12.1",
    "@nivo/calendar": "^0.74.0",
    "@nivo/core": "^0.74.0",
    "@nivo/line": "^0.74.0",
    "@nivo/tooltip": "^0.74.0",
    "@reach/router": "^1.3.4",
    "auth0-js": "^9.18.0",
    "aws-appsync-auth-link": "^3.0.7",
    "aws-appsync-subscription-link": "^3.0.9",
    "aws-sdk": "^2.1046.0",
    "clsx": "^1.1.1",
    "core-js": "^3.6.5",
    "d3-array": "^3.1.1",
    "date-fns": "^2.27.0",
    "dotenv": "^10.0.0",
    "exceljs": "^4.3.0",
    "file-saver": "^2.0.5",
    "formik": "^2.2.9",
    "formik-persist": "^1.1.0",
    "framer-motion": "^5.4.5",
    "fraql": "^1.2.1",
    "graphql": "^16.1.0",
    "husky": "^7.0.4",
    "immer": "^9.0.7",
    "linkifyjs": "^3.0.4",
    "lodash": "^4.17.21",
    "logrocket": "^2.1.2",
    "material-table": "^1.69.3",
    "msw": "^0.36.3",
    "password-validator": "^5.2.1",
    "randomcolor": "^0.6.2",
    "react": "17.0.2",
    "react-dom": "17.0.2",
    "react-dropzone-uploader": "^2.11.0",
    "react-elastic-carousel": "^0.11.5",
    "react-error-boundary": "^3.1.4",
    "react-google-docs-viewer": "^1.0.1",
    "react-icons": "^4.3.1",
    "react-intersection-observer": "^8.32.5",
    "react-lazy-load-image-component": "^1.5.1",
    "react-loading-skeleton": "^3.0.1",
    "react-prerendered-component": "^1.2.4",
    "regenerator-runtime": "0.13.7",
    "stream-browserify": "^3.0.0",
    "styled-components": "^5.3.3",
    "suneditor": "^2.41.3",
    "suneditor-react": "^3.3.1",
    "sw-precache": "^5.2.1",
    "tiny-slider-react": "^0.5.3",
    "tslib": "^2.0.0",
    "use-debounce": "^7.0.1",
    "uuid": "^8.3.2",
    "validate-password": "^1.0.4",
    "yup": "^0.32.11"
  },
  "devDependencies": {
    "@angular-devkit/schematics": "^13.0.4",
    "@babel/core": "7.12.13",
    "@babel/preset-typescript": "7.12.13",
    "@nrwl/cli": "13.2.4",
    "@nrwl/cypress": "13.2.4",
    "@nrwl/eslint-plugin-nx": "13.2.4",
    "@nrwl/jest": "13.2.4",
    "@nrwl/linter": "13.2.4",
    "@nrwl/node": "^13.2.4",
    "@nrwl/nx-cloud": "latest",
    "@nrwl/react": "13.2.4",
    "@nrwl/storybook": "^13.3.0",
    "@nrwl/tao": "^13.2.4",
    "@nrwl/web": "13.2.4",
    "@nrwl/workspace": "^13.2.4",
    "@storybook/addon-actions": "^6.4.9",
    "@storybook/addon-essentials": "~6.3.0",
    "@storybook/addon-knobs": "^6.4.0",
    "@storybook/addon-links": "^6.4.9",
    "@storybook/addon-storysource": "^6.4.9",
    "@storybook/builder-webpack5": "~6.3.0",
    "@storybook/manager-webpack5": "~6.3.0",
    "@storybook/react": "~6.3.0",
    "@svgr/webpack": "^5.4.0",
    "@testing-library/react": "12.1.2",
    "@testing-library/react-hooks": "7.0.2",
    "@types/auth0-js": "^9.14.5",
    "@types/jest": "27.0.2",
    "@types/node": "14.14.33",
    "@types/react": "17.0.30",
    "@types/react-dom": "17.0.9",
    "@types/react-lazy-load-image-component": "^1.5.2",
    "@types/tiny-slider-react": "^0.3.3",
    "@types/uuid": "^8.3.3",
    "@types/yup": "^0.29.13",
    "@typescript-eslint/eslint-plugin": "~4.33.0",
    "@typescript-eslint/parser": "~4.33.0",
    "@vitejs/plugin-react-refresh": "^1.3.1",
    "babel-jest": "27.2.3",
    "babel-loader": "8.1.0",
    "cypress": "^8.3.0",
    "eslint": "7.32.0",
    "eslint-config-prettier": "8.1.0",
    "eslint-plugin-cypress": "^2.10.3",
    "eslint-plugin-import": "2.25.2",
    "eslint-plugin-jsx-a11y": "6.4.1",
    "eslint-plugin-react": "7.26.1",
    "eslint-plugin-react-hooks": "4.2.0",
    "jest": "27.2.3",
    "nx-plugin-vite": "^1.1.0",
    "prettier": "^2.3.1",
    "react-test-renderer": "17.0.2",
    "storybook-theme-toggle": "^0.1.2",
    "ts-jest": "27.0.5",
    "typescript": "~4.4.3",
    "url-loader": "^3.0.0",
    "vite": "^2.7.1",
    "vite-tsconfig-paths": "^3.3.17"
  }
}
 

Базовый файл tsconfig.json:

 {
  "compileOnSave": false,
  "compilerOptions": {
    "rootDir": ".",
    "sourceMap": true,
    "declaration": false,
    "moduleResolution": "node",
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "importHelpers": true,
    "target": "es2015",
    "module": "esnext",
    "lib": ["dom", "dom.iterable", "esnext"],
    "skipLibCheck": true,
    "skipDefaultLibCheck": true,
    "baseUrl": ".",
    "paths": {
      "@schon/typings": ["libs/components/src/typings/index.ts"],
      "@schon/components": ["libs/components/src/index.ts"],
      "@schon/utils": ["libs/components/src/utils/index.ts"]
    }
  },
  "exclude": ["node_modules", "tmp"]
}

 

And this is vite’s tsconfig.json:

   "extends": "../../tsconfig.base.json",
  "compilerOptions": {
    "target": "es2017",
    "useDefineForClassFields": true,
    "lib": ["DOM", "DOM.Iterable", "ESNext"],
    "allowJs": true,
    "skipLibCheck": false,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "module": "ESNext",
    "moduleResolution": "Node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "jsx": "react-jsx",
    "noFallthroughCasesInSwitch": true
  },
  "include": ["src"]
}
 

Вот vite.config.ts:

 import { defineConfig } from 'vite';
import reactRefresh from '@vitejs/plugin-react-refresh';
import tsconfigPaths from 'vite-tsconfig-paths';

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [reactRefresh(), tsconfigPaths()],
  resolve: {
    alias: {
      stream: 'stream-browserify',
    },
  },
});

 

index.html:

 <!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
    <link
      href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700amp;display=swap"
      rel="stylesheet"
    />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1, shrink-to-fit=no"
    />
    <meta name="theme-color" content="#000000" />
    <meta
      name="description"
      content="Ayuda a la gestión administrativa y a la
      evaluación del estudiante bajo el nuevo sistema de competencias. ¡Regístrate ya!"
    />
    <!--
      manifest.json provides metadata used when your web app is added to the
      homescreen on Android. See https://developers.google.com/web/fundamentals/web-app-manifest/
    -->
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    <!--
      Notice the use of %PUBLIC_URL% in the tags above.
      It will be replaced with the URL of the `public` folder during the build.
      Only files inside the `public` folder can be referenced from the HTML.

      Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
      work correctly both with client-side routing and a non-root public URL.
      Learn how to configure a non-root public URL by running `npm run build`.
    -->
    <title>
      Schon - Plataforma educativa para evaluar a los estudiantes usando el
      sistema de competencias.
    </title>
    <!-- Global site tag (gtag.js) - Google Analytics -->
    <script
      async
      src="https://www.googletagmanager.com/gtag/js?id=UA-174022724-1"
    ></script>
    <script>
      window.dataLayer = window.dataLayer || [];
      function gtag() {
        dataLayer.push(arguments);
      }
      gtag('js', new Date());

      gtag('config', 'UA-174022724-1');
    </script>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
    <!--
      This HTML file is a template.
      If you open it directly in the browser, you will see an empty page.

      You can add webfonts, meta tags, or analytics to this file.
      The build step will place the bundled scripts into the <body> tag.

      To begin the development, run `npm start` or `yarn start`.
      To create a production bundle, use `npm run build` or `yarn build`.
    -->

    <!-- CUSTOM DOWN BELOW-->
    <!-- 
      add entry for snowpack, only used in dev, it is pruned in production.
    -->
    <script type="module" src="/src/index.tsx"></script>
  </body>
</html>

 

Есть идеи? Я попробую запустить новый проект и установить зависимости одну за другой… Если это не сработает, я попробую Snowpack вместо этого.

Webpack занимает около 3-4 минут, чтобы запустить сервер разработки, и это недопустимо для разработки.

Редактировать: я хотел добавить, что я добавлял только один пустой файл React (после рендеринга DOM), и он загрузит этот фрагмент и выдаст мне ошибку.

Комментарии:

1. О боже, я только что узнал, что это правда. index.html был единственным, у кого были проблемы. Я сделал переход из того, который у меня был из Webpack, и это вызвало ряд проблем.

Ответ №1:

Примечание: я основной участник Nxext

Я думаю, что этот проект может быть полезен для вас https://nxext.dev/docs/react/overview . Недавно мы только что написали плагин vite для NX и запустили react.

Если вам нужна какая-либо помощь, я буду рад выполнить сопряжение program, чтобы решить эту проблему для вас

Комментарии:

1. Это отличная новость! Можно ли использовать его с postcss and tailwind@3 ?

2. Я просто попытался установить его и получил следующую ошибку: Unable to resolve @nxext/react:app. Cannot find module '/Users/knf/dev/test/node_modules/@nxext/react/generators.json'

3. вы установили @nxext / react также да, tailwind работает

4. @knoefel если проблема останется, можете ли вы поделиться журналами на github.com/nxext/nx-extensions/issues пожалуйста

5. Спасибо @Джордан Холл! Кто-то оказался быстрее меня, поскольку проблема уже существует. 😉

Ответ №2:

Все готово!!

Проблема была (действительно) неправильной index.html . Не просто отправляйте свой index.html из Webpack, так как это не сработает.

Я вернул его к тому, что было в Vite, и это сработало!