简体   繁体   English

如何配置 webpack 以从其他 lerna 包中转译文件(从 create-react-app 中弹出)

[英]How to config webpack to transpile files from other lerna packages (ejected from create-react-app)

I'm trying to build a lerna package with a create-react-app package and a simple component library.我正在尝试使用create-react-app package 和一个简单的组件库构建一个 lerna package。 My component is as follows:我的组件如下:

import React, { Component } from "react";
import PropTypes from "prop-types";

    class Layout extends Component {
        render = () => {
            let style = {
                fontSize: 14,
                fontFamily:
                    "-apple-system, system-ui, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', sans-serif",
                fontWeight: 400
            };

            return <div style={style}>{this.props.children}</div>;
        };
    }

    export default Layout;

And my original create-react-app is as follows:而我原来create-react-app如下:

index.js index.js

import React from 'react';
import ReactDOM from 'react-dom';

import App from './components/app/App/App';

ReactDOM.render(<App />, document.getElementById('root'));

App.js应用程序.js

import React, { Component } from "react";

import Layout from "@quadfloor/webux/lib/Layout";

class App extends Component {
    render = () => {
        return (
            <Layout>
                Hello!
            </Layout>
        );
    };
}

export default App;

When running, I'm getting the following error:运行时,我收到以下错误:

../webux/lib/Layout/index.js
SyntaxError: /Volumes/workspace/dev/packages/webux/lib/Layout/index.js: Support for the experimental syntax 'classProperties' isn't currently enabled (5:12):

  3 |
  4 | class Layout extends Component {
> 5 |     render = () => {
    |            ^
  6 |         let style = {
  7 |             fontSize: 14,
  8 |             fontFamily:

Add @babel/plugin-proposal-class-properties (https://git.io/vb4SL) to the 'plugins' section of your Babel config to enable transformation.

This error happens because create-react-app does not transpile files outside its project.发生此错误是因为create-react-app不会在其项目之外转换文件。 As my component Layout resides in another lerna package in another directory, it is not transpiled.由于我的组件Layout位于另一个目录中的另一个 lerna package 中,因此它不会被转译。

In order to solve it, I've ejected my create-react-app application and end up with the following webpack configuration file, where I've added the ====INCLUDED=== piece of code to set the input directories (I've added the directory immediately above the project, as this will point to my lerna \packages directory, so all packages files are processed:为了解决它,我退出了我的create-react-app应用程序并最终得到了以下 webpack 配置文件,我在其中添加了====INCLUDED===一段代码来设置input目录(我在项目上方添加了目录,因为这将指向我的 lerna \packages目录,因此所有包文件都被处理:

  ...
    resolve: {
      // This allows you to set a fallback for where Webpack should look for modules.
      // We placed these paths second because we want `node_modules` to "win"
      // if there are any conflicts. This matches Node resolution mechanism.
      // https://github.com/facebook/create-react-app/issues/253
      modules: ['node_modules', paths.appNodeModules].concat(
        modules.additionalModulePaths || []
      ),
      // These are the reasonable defaults supported by the Node ecosystem.
      // We also include JSX as a common component filename extension to support
      // some tools, although we do not recommend using it, see:
      // https://github.com/facebook/create-react-app/issues/290
      // `web` extension prefixes have been added for better support
      // for React Native Web.
      extensions: paths.moduleFileExtensions
        .map(ext => `.${ext}`)
        .filter(ext => useTypeScript || !ext.includes('ts')),
      alias: {
        // Support React Native Web
        // https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/
        'react-native': 'react-native-web',
        // Allows for better profiling with ReactDevTools
        ...(isEnvProductionProfile && {
          'react-dom$': 'react-dom/profiling',
          'scheduler/tracing': 'scheduler/tracing-profiling',
        }),
        ...(modules.webpackAliases || {}),
      },
      plugins: [
        // Adds support for installing with Plug'n'Play, leading to faster installs and adding
        // guards against forgotten dependencies and such.
        PnpWebpackPlugin,
        // Prevents users from importing files from outside of src/ (or node_modules/).
        // This often causes confusion because we only process files within src/ with babel.
        // To fix this, we prevent you from importing files out of src/ -- if you'd like to,
        // please link the files into your node_modules/ and let module-resolution kick in.
        // Make sure your source files are compiled, as they will not be processed in any way.
        new ModuleScopePlugin(paths.appSrc, [paths.appPackageJson]),
      ],
    },
    resolveLoader: {
      plugins: [
        // Also related to Plug'n'Play, but this time it tells Webpack to load its loaders
        // from the current package.
        PnpWebpackPlugin.moduleLoader(module),
      ],
    },
    module: {
      strictExportPresence: true,
      rules: [
        // Disable require.ensure as it's not a standard language feature.
        { parser: { requireEnsure: false } },

        // First, run the linter.
        // It's important to do this before Babel processes the JS.
        {
          test: /\.(js|mjs|jsx|ts|tsx)$/,
          enforce: 'pre',
          use: [
            {
              options: {
                cache: true,
                formatter: require.resolve('react-dev-utils/eslintFormatter'),
                eslintPath: require.resolve('eslint'),
                resolvePluginsRelativeTo: __dirname,

              },
              loader: require.resolve('eslint-loader'),
            },
          ],
          //=================== INCLUDED =====================/
          //
          // Included the lenrna packages directory (up directory) 
          // in order to transpile all files from other packages.
          //
          //===================================================
          include: [path.resolve(__dirname, "../.."), paths.appSrc],
        },
        {
          // "oneOf" will traverse all following loaders until one will
          // match the requirements. When no loader matches it will fall
          // back to the "file" loader at the end of the loader list.
          oneOf: [
            // "url" loader works like "file" loader except that it embeds assets
            // smaller than specified limit in bytes as data URLs to avoid requests.
            // A missing `test` is equivalent to a match.
            {
              test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
              loader: require.resolve('url-loader'),
              options: {
                limit: imageInlineSizeLimit,
                name: 'static/media/[name].[hash:8].[ext]',
              },
            },
            // Process application JS with Babel.
            // The preset includes JSX, Flow, TypeScript, and some ESnext features.
            {
              test: /\.(js|mjs|jsx|ts|tsx)$/,
              /// Renato Mendes
              /// This was added to support transpiling of monorepo modules.
              /// See https://github.com/webpack/webpack/issues/6799
              ///
              /// Original:
              /// include: paths.appSrc
              ///
              include: [path.resolve(__dirname, "../.."), path.resolve(paths.lernaRoot + "/packages"), paths.appSrc],
              //              include: paths.appSrc,
              include: [paths.lernaRoot, paths.appSrc],
              loader: require.resolve('babel-loader'),
              options: {
                customize: require.resolve(
                  'babel-preset-react-app/webpack-overrides'
                ),

                plugins: [
                  [
                    require.resolve('babel-plugin-named-asset-import'),
                    {
                      loaderMap: {
                        svg: {
                          ReactComponent:
                            '@svgr/webpack?-svgo,+titleProp,+ref![path]',
                        },
                      },
                    },
                  ],
                ],
                // This is a feature of `babel-loader` for webpack (not Babel itself).
                // It enables caching results in ./node_modules/.cache/babel-loader/
                // directory for faster rebuilds.
                cacheDirectory: true,
                // See #6846 for context on why cacheCompression is disabled
                cacheCompression: false,
                compact: isEnvProduction,
              },
            },
            // Process any JS outside of the app with Babel.
            // Unlike the application JS, we only compile the standard ES features.
            {
              test: /\.(js|mjs)$/,
              exclude: /@babel(?:\/|\\{1,2})runtime/,
              loader: require.resolve('babel-loader'),
              options: {
                babelrc: false,
                configFile: false,
                compact: false,
                presets: [
                  [
                    require.resolve('babel-preset-react-app/dependencies'),
                    { helpers: true },
                  ],
                ],
                cacheDirectory: true,
                // See #6846 for context on why cacheCompression is disabled
                cacheCompression: false,

                // If an error happens in a package, it's possible to be
                // because it was compiled. Thus, we don't want the browser
                // debugger to show the original code. Instead, the code
                // being evaluated would be much more helpful.
                sourceMaps: false,
              },
            },
            // "postcss" loader applies autoprefixer to our CSS.
            // "css" loader resolves paths in CSS and adds assets as dependencies.
            // "style" loader turns CSS into JS modules that inject <style> tags.
            // In production, we use MiniCSSExtractPlugin to extract that CSS
            // to a file, but in development "style" loader enables hot editing
            // of CSS.
            // By default we support CSS Modules with the extension .module.css
            {
              test: cssRegex,
              exclude: cssModuleRegex,
              use: getStyleLoaders({
                importLoaders: 1,
                sourceMap: isEnvProduction && shouldUseSourceMap,
              }),
              // Don't consider CSS imports dead code even if the
              // containing package claims to have no side effects.
              // Remove this when webpack adds a warning or an error for this.
              // See https://github.com/webpack/webpack/issues/6571
              sideEffects: true,
            },
            // Adds support for CSS Modules (https://github.com/css-modules/css-modules)
            // using the extension .module.css
            {
              test: cssModuleRegex,
              use: getStyleLoaders({
                importLoaders: 1,
                sourceMap: isEnvProduction && shouldUseSourceMap,
                modules: true,
                getLocalIdent: getCSSModuleLocalIdent,
              }),
            },
            // Opt-in support for SASS (using .scss or .sass extensions).
            // By default we support SASS Modules with the
            // extensions .module.scss or .module.sass
            {
              test: sassRegex,
              exclude: sassModuleRegex,
              use: getStyleLoaders(
                {
                  importLoaders: 2,
                  sourceMap: isEnvProduction && shouldUseSourceMap,
                },
                'sass-loader'
              ),
              // Don't consider CSS imports dead code even if the
              // containing package claims to have no side effects.
              // Remove this when webpack adds a warning or an error for this.
              // See https://github.com/webpack/webpack/issues/6571
              sideEffects: true,
            },
            // Adds support for CSS Modules, but using SASS
            // using the extension .module.scss or .module.sass
            {
              test: sassModuleRegex,
              use: getStyleLoaders(
                {
                  importLoaders: 2,
                  sourceMap: isEnvProduction && shouldUseSourceMap,
                  modules: true,
                  getLocalIdent: getCSSModuleLocalIdent,
                },
                'sass-loader'
              ),
            },
            // "file" loader makes sure those assets get served by WebpackDevServer.
            // When you `import` an asset, you get its (virtual) filename.
            // In production, they would get copied to the `build` folder.
            // This loader doesn't use a "test" so it will catch all modules
            // that fall through the other loaders.
            {
              loader: require.resolve('file-loader'),
              // Exclude `js` files to keep "css" loader working as it injects
              // its runtime that would otherwise be processed through "file" loader.
              // Also exclude `html` and `json` extensions so they get processed
              // by webpacks internal loaders.
              exclude: [/\.(js|mjs|jsx|ts|tsx)$/, /\.html$/, /\.json$/],
              options: {
                name: 'static/media/[name].[hash:8].[ext]',
              },
            },
            // ** STOP ** Are you adding a new loader?
            // Make sure to add the new loader(s) before the "file" loader.
          ],
        },
      ],
    }
    ...

I'm still getting the error, as my external component is not getting transpiled.我仍然收到错误消息,因为我的外部组件没有被转译。

How to make the above webpack config transpile my code that resides in another package of my lerna project?如何使上述 webpack 配置转译驻留在我的 lerna 项目的另一个 package 中的代码? Any other config missing?是否缺少其他配置? What am I doing wrong?我究竟做错了什么?

The bad news: This is a common problem.坏消息:这是一个常见问题。 Create React App doesn't support monorepos , as of ~3.2.0 / late 2019. If you want to share components between lerna sibling packages, many people either avoid using "CRApp", or, include a build script in their component library packages and commit and export pre-transpiled ES5 files. Create React App 不支持 monorepos ,截至 ~3.2.0 / 2019 年末。如果你想在 lerna 兄弟包之间共享组件,许多人要么避免使用“CRApp”,要么在他们的组件库包中包含构建脚本并提交和导出预编译的 ES5 文件。

The good news: I found a fix that seems to work, and doesn't require ejecting CRA.好消息:我找到了一个似乎有效的修复程序,并且不需要退出 CRA。 Tested with both local build and test deploy to github pages.通过本地构建和测试部署到 github 页面进行测试。

It uses craco , which provides an API for editing CRA's webpack config without ejecting.它使用craco ,它提供了一个 API 用于编辑 CRA 的 webpack 配置而不弹出。 Craco has plugins which add webpack loaders etc; Craco 有添加 webpack 加载器等的插件; we'll need craco-babel-loader :我们需要craco-babel-loader

npm i --save @craco/craco craco-babel-loader npm i --save @craco/craco craco-babel-loader

...then there are some further CRACO setup steps, check https://github.com/gsoft-inc/craco/blob/master/packages/craco/README.md#installation for the latest. ...然后还有一些进一步的 CRACO 设置步骤,请查看https://github.com/gsoft-inc/craco/blob/master/packages/craco/README.md#installation以获取最新信息。 At time of writing, you need to replace the following CRA scripts in package.json :在撰写本文时,您需要替换package.json中的以下 CRA scripts

  • react-scripts start => craco start react-scripts start => craco start
  • react-scripts build => craco build react-scripts build => craco build
  • react-scripts test => craco test react-scripts test => craco test

Then we need to create a config file, craco.config.js , in the root of the CRA/craco package that receives ES6+ JSX components from sibling packages, and we need to list the package names to send to babel:然后我们需要在 CRA/craco package 的根目录下创建一个配置文件craco.config.js ,该文件从兄弟包中接收ES6+ JSX 组件,我们需要列出 package 名称以发送到 babel:

// crago.config.js
// see: https://github.com/sharegate/craco

const path = require('path')
const fs = require('fs')
const cracoBabelLoader = require('craco-babel-loader')

// Handle relative paths to sibling packages
const appDirectory = fs.realpathSync(process.cwd())
const resolvePackage = relativePath => path.resolve(appDirectory, relativePath)

module.exports = {
  plugins: [
    {
      plugin: cracoBabelLoader,
      options: {
        includes: [
          // No "unexpected token" error importing components from these lerna siblings:
          resolvePackage('../some-component-library'),
          resolvePackage('../more-components'),
          resolvePackage('../another-components-package'),
        ],
      },
    },
  ],
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在Webpack配置中添加带有弹出的create-react-app项目的Ant Design - add Ant Design with ejected create-react-app project in Webpack config 将Sass(.scss)添加到弹出的create-react-app配置中 - Add Sass (.scss) to ejected create-react-app config create-react-app webpack 配置和文件在哪里? - where is create-react-app webpack config and files? 将 webpack 4 更新为 webpack 5 在现有的 create-react-app 上用 react-app-rewired 弹出 - Update webpack 4 to webpack 5 on an existing create-react-app ejected with react-app-rewired 如何将流程类型添加到弹出的create-react-app? - How to add flowtype to an ejected create-react-app? 如何检查 create-react-app 项目是否已被弹出? - How to check if a create-react-app project has been ejected or not? 弹出的create-react-app的快速路由 - Express Routes for ejected create-react-app 从 create-react-app 项目中排除 Webpack 的依赖项 - Exclude Dependency from Webpack from create-react-app project 如何使用 webpack 使 create-react-app 支持 .mjs 文件? - How to make create-react-app support .mjs files with webpack? 使用babel-preset-env进行转换,而无需从create-react-app弹出 - Transpile using babel-preset-env without ejecting from create-react-app
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM