Related
I'm trying to build a lerna package with a create-react-app package and a simple component library. 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:
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
import React, { Component } from "react";
import Layout from "#project/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. As my component Layout resides in another lerna package in another directory, it is not transpiled.
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:
...
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? 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.
The good news: I found a fix that seems to work, and doesn't require ejecting CRA. Tested with both local build and test deploy to github pages.
It uses craco, which provides an API for editing CRA's webpack config without ejecting. Craco has plugins which add webpack loaders etc; we'll need 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. At time of writing, you need to replace the following CRA scripts in package.json:
react-scripts start => craco start
react-scripts build => craco build
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:
// 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'),
],
},
},
],
}
I've been trying to use sass-loader on webpack v4, but it fails to load scss files in a React component with TypeScript.
Here is a simplified snippet of the code.
//index.tsx
import * as React from 'react';
import './styles.scss';
const Navigation = () => {
return (<div className="app-bar"></div>)
}
//styles.scss
.app-bar {
background-color: #2196f3;
}
The following code is from my webpack config.
module: {
rules: [
//loaders for jsx, tsx etc
{
test: /\.(css|scss)$/,
use: [
{ loader: 'style-loader' },
{
loader: 'css-loader',
options: {
modules: true
}
},
{ loader: 'sass-loader' }
]
}]
},
plugins: [
new MiniCssExtractPlugin({
filename: "[name].css",
chunkFilename: "[id].css"
}),
new CleanWebpackPlugin(),
]
I followed the official doc's example, but it fails to load the styles.scss.
Just in case, I re-installed style-loader, css-loader, sass-loader (and node-sass), but it didn't solve the error.
The error message is ...
Module build failed (from ./node_modules/sass-loader/lib/loader.js):
I'm running webpack via Laravel Mix, but don't know if Laravel has anything to do with it.
What caused this issue? Any advice will be appreciated.
You dont need to put css in the test section because the sass-loader and css-loader will take care for you and it will transform your scss to css file
Below is my config
{
test: /\.scss$/,
use: [
//'style-loader' was the culprit, so I just needed to remove it
MiniCssExtractPlugin.loader,
{
loader: "css-loader",
options: {
minimize: true,
sourceMap: true
}
},
{
loader: "sass-loader"
}
]
I seem to remember having the same issues with webpack. I switched from SASS to Styled Components, it's a css-in-js library. I was wary at first but it's great.
https://www.styled-components.com/
It allows you to change CSS styles programmatically using React props. For example if I want to change the opacity of a menu when a button is clicked I can do it like this:
opacity: ${props => (props.menuOpen ? 1 : 0)};
That’s just one benefit, check the docs to see others. I find using React with styled-components is a great way to work. You have your JS, CSS and HTML all being generated in one place.
I am attempting to upgrade to Babel 7, on a front end application using React 15.6.2 and Relay 1.6.2
The webpack bundle builds successfully.
However I get the following console error in the browser.
webpack_require(...).forwardRef is not a function
at buildReactRelayContainer
I am using webpack 3.12.0
And have the babel-plugin-relay in dev dependencies, and set at the top of the plugins in .babelrc, and set at the top of the plugins list in webpack.
Note at this stage I cannot upgrade to React 16 due to a library that uses the deprecated propTypes from React 15
.babelrc
{
"presets": [
"#babel/preset-env",
"#babel/preset-react"
],
"sourceMaps": true,
"plugins": [
"relay",
"babel-plugin-ramda",
"#babel/plugin-syntax-dynamic-import",
"#babel/plugin-syntax-import-meta",
"#babel/plugin-proposal-class-properties",
"#babel/plugin-proposal-json-strings",
[
"#babel/plugin-proposal-decorators",
{
"legacy": true
}
],
"#babel/plugin-proposal-function-sent",
"#babel/plugin-proposal-export-namespace-from",
"#babel/plugin-proposal-numeric-separator",
"#babel/plugin-proposal-throw-expressions",
"#babel/plugin-proposal-export-default-from",
"#babel/plugin-proposal-logical-assignment-operators",
"#babel/plugin-proposal-optional-chaining",
[
"#babel/plugin-proposal-pipeline-operator",
{
"proposal": "minimal"
}
],
"#babel/plugin-proposal-nullish-coalescing-operator",
"#babel/plugin-proposal-do-expressions",
"#babel/plugin-proposal-function-bind"
]
}
webpack
...
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: [
"#babel/preset-env",
"#babel/preset-react",
{
"plugins": [
["relay", {"schema": "./graphql_schema_builds/private/venue/schema.graphql"}],
"ramda"
]
}
]
}
}
},
...
you are trying to mix things together which don't play well together. You are best off upgrading to the latest version of React (16.6~) and the latest version of webpack (4.3.0). They will play well with Babel 7. It will be a drastic change, but worth the updates! I am currently updating a React Workflow I had created last year which originally used webpack 3.6, Babel 6+, and React < 16.6, but when I created a new React Application in which React 16.6~ was added as well as webpack 4, and I tried to implement Babel with old package naming, it did not work. My webpack config did not work either. I had to make some major changes. Here is the link to my updated React workflow repo presentation/dlocumentation: https://github.com/interglobalmedia/react-workflow-updated-2018 The update is not complete yet, but you can follow my progress if you like! It should be completed very soon!
I used create-react-app to create a react application.
After I run eject, I am unable to use the spread operator as follows:
//eslint-disable-next-line
const { children, ...attributes } = this.props; //Line 19
It keeps giving me this error when I run yarn start
Line 19: Parsing error: Unexpected token ..
Webpack Dev Server
I have tried adding all the presets and the transform plugin to both webpack dev server config and .babelrc but no luck
// Process JS with Babel.
{
test: /\.(js|jsx|mjs)$/,
include: paths.appSrc,
loader: require.resolve('babel-loader'),
options: {
presets:['react','es2015','env',"stage-2"],
plugins: ["transform-object-rest-spread"],
// 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,
},
},
// "postcss" loader app
And in the babel rc file as well
//.babelrc
{
"presets":["env","react","stage-2"],
"plugins": [
["transform-object-rest-spread", { "useBuiltIns": true }]
]
}
It works fine if I don't eject the script.
So the problem turned out to be eslint.
Webpack config was loading it before babel
Adding parser options fixed it.
{
test: /\.(js|jsx|mjs)$/,
enforce: 'pre',
use: [
{
options: {
formatter: eslintFormatter,
eslintPath: require.resolve('eslint'),
"extends": "airbnb",
"parserOptions":{
"ecmaFeatures": {
"experimentalObjectRestSpread": true
}
}
},
loader: require.resolve('eslint-loader'),
},
],
include: paths.appSrc,
},
Updated the #babel with this:
npm install #babel/runtime#latest did the work
React beginner here. My app uses create-react-app, and I'm pulling in react-slick for a carousel. I'm trying to follow the directions that are provided in the setup for react-slick, but the following doesn't work for me:
#import "~slick-carousel/slick/slick.css";
#import "~slick-carousel/slick/slick-theme.css";
I get the following error:
./src/components/Homepage.scss
Module not found: Can't resolve '~slick-carousel/slick/slick.css' in '/Users/simon/Dev/frischideas/site-new/src/components'
It works if I add the css to index.html from the CDN, but I'd rather avoid that network call, as I believe it's affecting the rendering of the page on initial load.
I tried following the instructions for configuring create-react-app to use relative paths, but that wasn't working for me either. Maybe I'm completely misunderstanding, but I thought the ~ notation would allow me to import scss from a package in /node_modules.
Any suggestions/clarification would be greatly appreciated.
Update: adding the setup from my webpack.config file (most of which is the default from create-react-app).
{
test: /\.scss$/,
use: [
require.resolve('classnames-loader'),
require.resolve('style-loader'), {
loader: require.resolve('css-loader'),
options: {
importLoaders: 1,
modules: 1,
localIdentName: "[name]__[local]___[hash:base64:5]"
},
},{
loader: require.resolve('postcss-loader'),
options: {
// Necessary for external CSS imports to work
// https://github.com/facebookincubator/create-react-app/issues/2677
ident: 'postcss',
plugins: () => [
require('postcss-flexbugs-fixes'),
autoprefixer({
browsers: [
'>1%',
'last 6 versions',
'Firefox ESR',
'not ie < 9', // React doesn't support IE8 anyway,'
],
remove: false,
flexbox: 'no-2009',
}),
],
},
},{
loader: require.resolve('sass-loader'),
options: {
outputStyle: 'expanded'
}
}
],
}
you change to be this :
import "slick-carousel/slick/slick.css";
import "slick-carousel/slick/slick-theme.css";
delete ~
you might have missed this:
npm install slick-carousel
You Also need to install slick-carousel for CSS and fonts.
That's the trick here.
Cheers...
First, install slick-carousel
npm install slick-carousel --save
If you are using yarn, you can use
yarn add slick-carousel
Then import CSS files in your App.js file.
import "slick-carousel/slick/slick.css";
import "slick-carousel/slick/slick-theme.css";
I was struggling with this issue and I finally find the solution:
just go inside of your node_modules folder and find slick-carousel folder
inside of that find slick.scss and slick-theme.scss from slick folder and open them up
create two seperate files with names of _slick.scss and _slickTheme.scss inside of your style folders of your project
copy all from slick.scss and slick-theme.scss and put them in your newly created files ( _slick.scss and _slickTheme.scss )
import them in your app.scssfile
now if you are using webpack like me, I'm guessing that you getting can't resolve './ajax-loader.gif' error and can't resolve font error after that
in fact those files is been used by slick-carousel css it self and for that we can just simple go inside your newly created _slickTheme.scss and find these lines
/* Slider */
.slick-list {
.slick-loading & {
background: #fff slick-image-url("ajax-loader.gif") center center no-repeat;
}
}
/* Icons */
#if $slick-font-family == "slick" {
#font-face {
font-family: "slick";
src: slick-font-url("slick.eot");
src: slick-font-url("slick.eot?#iefix") format("embedded-opentype"), slick-font-url("slick.woff") format("woff"), slick-font-url("slick.ttf") format("truetype"), slick-font-url("slick.svg#slick") format("svg");
font-weight: normal;
font-style: normal;
}
}
comment them out
You need to have appropriate loaders.
Use style-loader in combination with css-loader for the CSS.
Use file-loader and url-loader in order to load the fonts and images linked within CSS files.
(Here are configuration settings for the file-loader)
So at the end, your webpack.config.js should contain something like this:
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: [
"#babel/preset-env",
"#babel/preset-react"
].map(require.resolve)
}
}
},
{
test: /\.css$/,
use: [
{loader: "style-loader"},
{loader: "css-loader"}
]
},
{
test: /\.(png|jpg|gif)$/i,
use: [
{
loader: 'url-loader',
options: {
limit: 8192
}
}
]
},
{
test: /\.(woff(2)?|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/,
use: [{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'fonts/'
}
}]
}
]
},
After that, you can simply import styles into your application entry point (e.g. /src/index.js):
import 'slick-carousel/slick/slick.css';
import 'slick-carousel/slick/slick-theme.css';
It fails because you are importing css modules in your app, and styles from slick are not applied because they are getting cached.
I've fixed it in my project like below:
In your style.scss files put this
:global {
#import 'node_modules/slick-carousel/slick/slick';
}
You are missed installing a slick carousel. try this code
npm install slick-carousel
Click here for more Details
To import styles, make sure that you have installed slick-carousel first:
npm install slick-carousel --save
then:
import "~slick-carousel/slick/slick.css";
import "~slick-carousel/slick/slick-theme.css";
Note: But be aware slick-carousel has a peer-dependancy on jQuery
which you, or your colleagues may not like to see in your console
output, so you can always grab the CSS from there and convert it into
any CSS in JS solution that you might be using.
This information was taken from react-slick documentation page.
you need to install react-slick CSS files without ~ sign like this:
import "slick-carousel/slick/slick.css";
import "slick-carousel/slick/slick-theme.css";
and you need to import them also in the component that is showing your slick slider
for example, if you have a **slider component ** that is going to be used in Home component, you need to import slick CSS files in Home too. it worked for me.
and if you are changing direction to rtl, you need to use ltr for slider
and check slick-carousel to be installed