[英]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.