I am creating a npm package with react components, providers, and other utilities. The idea is use this npm package in other projects. I configured rollup to create the builds but when I try to use it in another project I got a "React is not defined" error.
Here is my code and the error in detail:
package.json:
{
"name": "myapp",
"version": "0.1.14",
"description": "Npm package.",
"main": "lib/index.cjs.js",
"module": "lib/index.esm.js",
"files": [
"dist",
"README.md"
],
"scripts": {
"start": "react-scripts start",
"build": "npx rollup -c",
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": ""
},
"author": "",
"license": "ISC",
"dependencies": {
"#babel/polyfill": "^7.12.1",
"#fluentui/react": "8.52.2",
"#rjsf/core": "4.2.0",
"#rjsf/fluent-ui": "4.2.0",
"#types/node": "^17.0.21",
"#types/react": "^17.0.40",
"#types/react-dom": "^17.0.13",
"axios": "^0.25.0",
"office-ui-fabric-core": "^11.0.0",
"react-query": "^3.34.19",
"react-simple-resizer": "^2.1.0"
},
"peerDependencies": {
"react": ">=16.8.0",
"react-dom": ">=16.8.0",
"#fluentui/react": "8.52.2"
},
"devDependencies": {
"#babel/cli": "^7.17.0",
"#babel/core": "^7.17.0",
"#babel/preset-env": "^7.16.11",
"#babel/preset-react": "^7.16.7",
"#fluentui/example-data": "^8.4.0",
"#rollup/plugin-babel": "^5.3.0",
"#rollup/plugin-commonjs": "^21.0.1",
"#rollup/plugin-node-resolve": "^13.1.3",
"#rollup/plugin-replace": "^4.0.0",
"#rollup/plugin-typescript": "^8.3.1",
"react-scripts": "^5.0.0",
"rollup": "^2.67.1",
"rollup-plugin-import-css": "^3.0.3",
"rollup-plugin-includepaths": "^0.2.4",
"rollup-plugin-peer-deps-external": "^2.2.4",
"rollup-plugin-terser": "^7.0.2",
"typescript": "^4.6.2",
"react": "^17.0.2",
"react-dom": "^17.0.2"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
rollup.config.js:
import babel from "#rollup/plugin-babel";
import resolve from "#rollup/plugin-node-resolve";
import commonjs from "#rollup/plugin-commonjs";
import includePaths from "rollup-plugin-includepaths";
import peerDepsExternal from "rollup-plugin-peer-deps-external";
import { terser } from "rollup-plugin-terser";
import pkg from "./package.json";
import typescript from "#rollup/plugin-typescript";
import css from "rollup-plugin-import-css";
import replace from "#rollup/plugin-replace";
const outputs = [
{
file: pkg.main,
format: "umd",
},
{
file: pkg.module,
format: "es",
}
]
const external = [
...Object.keys(pkg.peerDependencies || {})
].map(name => RegExp(`^${name}($|/)`))
const config = outputs.map(({ file, format }) => ({
input: "src/lib/index.js",
output: {
file,
format,
name: "ReactPackage",
globals: {
react: "React",
"react-dom": "ReactDOM",
"#fluentui/react": "FluentUI",
}
},
external,
plugins: [
typescript(),
peerDepsExternal(),
includePaths({
include: {},
paths: ["src/lib"],
external: Object.keys(pkg.dependencies),
extensions: ['.js', '.json', '.html', '.tsx', '.ts']
}),
css(),
babel({
babelHelpers: "bundled",
exclude: "node_modules/**",
configFile: "./babel.config.rollup.js",
}),
resolve({
browser: true
}),
commonjs(),
terser(),
replace({
preventAssignment: true,
'process.env.NODE_ENV': JSON.stringify('production')
})
],
}));
export default config;
Babel:
const pkg = require('./package.json');
module.exports = {
presets: [
[
'#babel/preset-env',
{
modules: false,
targets: pkg.browserslist.production,
},
],
[
'#babel/preset-react',
{
"runtime": "automatic"
}
]
],
ignore: ['node_modules/**'],
};
The provider that I am trying to use but I get an "React is not defined" error:
Provider.ts:
import PContext from "../contexts/pContext";
import { QueryClient, QueryClientProvider } from "react-query";
import React, { useState } from "react";
const queryClient = new QueryClient();
const PProvider = ({ children, url }) => {
const [active, setActive] = useState(null);
return (
<PContext.Provider
value={{
url,
active,
setActive
}}
>
<QueryClientProvider client={queryClient}>
{children}
</QueryClientProvider>
</PContext.Provider>
);
};
export default PProvider;
Related
I am creating a chrome extension that is mainly served in a popup script.
Manifest.json
// public/manifest.json
{
"manifest_version": 3,
"version": "3.0.0",
"name": "__MSG_appName__",
"description": "__MSG_appDesc__",
"default_locale": "en",
"author": "lbragile",
"homepage_url": "some_url_not_relevant_to_question_at_hand",
"permissions": ["tabs", "storage"],
"optional_permissions": ["contextMenus", "alarms", "downloads", "downloads.shelf"],
"icons": {
"16": "images/logo16.png",
"48": "images/logo48.png",
"128": "images/logo128.png"
},
"action": {
"default_icon": {
"16": "images/logo16.png",
"48": "images/logo48.png",
"128": "images/logo128.png"
},
"default_popup": "index.html",
"default_title": "title"
},
"background": {
"service_worker": "background.js"
},
"incognito": "split"
}
Package.json
// package.json
{
"name": "name",
"version": "0.0.1",
"description": "description",
"author": "lbragile",
"private": true,
"dependencies": {
"nanoid": "^3.1.30",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-redux": "^7.2.5",
"react-router-dom": "^5.3.0",
"react-scripts": "4.0.3",
"redux": "^4.1.1"
},
"devDependencies": {
"#babel/core": "^7.13.14",
"#babel/preset-env": "^7.13.12",
"#babel/preset-react": "^7.13.13",
"#fortawesome/fontawesome-svg-core": "^1.2.36",
"#fortawesome/free-regular-svg-icons": "^5.15.4",
"#fortawesome/free-solid-svg-icons": "^5.15.4",
"#fortawesome/react-fontawesome": "^0.1.15",
"#types/chrome": "0.0.159",
"#types/express": "^4.17.13",
"#types/node": "^16.10.3",
"#types/react": "^17.0.15",
"#types/react-dom": "^17.0.9",
"#types/react-redux": "^7.1.19",
"#types/react-router-dom": "^5.1.8",
"#types/redux-immutable-state-invariant": "^2.1.2",
"#types/remote-redux-devtools": "^0.5.5",
"#types/styled-components": "^5.1.12",
"#typescript-eslint/eslint-plugin": "^5.0.0",
"#typescript-eslint/parser": "^5.0.0",
"babel-loader": "^8.2.3",
"babel-plugin-styled-components": "^1.13.2",
"copy-webpack-plugin": "^9.0.1",
"eslint": "^7.11.0",
"eslint-plugin-react": "^7.24.0",
"eslint-plugin-react-hooks": "^4.2.0",
"eslint-plugin-styled-components-a11y": "0.0.34",
"redux-devtools-extension": "^2.13.9",
"styled-components": "^5.3.0",
"stylelint": "^13.13.1",
"stylelint-config-standard": "^22.0.0",
"ts-loader": "^9.2.6",
"typescript": "^4.3.5",
"url-loader": "^4.1.1",
"webpack": "^5.59.1",
"webpack-cli": "^4.9.1"
},
"scripts": {
"lint": "npx eslint {src,public}/**/**/*.[jt]s -c config/.eslintrc.js --ignore-path .gitignore .",
"lint:style": "npx stylelint {src,public}/**/**/*.css --config config/.stylelintrc.json",
"start": "webpack --config config/webpack.config.js --watch --progress"
},
"babel": {
"extends": "./config/.babelrc.json"
},
"eslintConfig": {
"extends": "./config/.eslintrc.js"
},
"stylelint": {
"extends": "./config/.stylelintrc.json"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
Webpack
// config/webpack.config.js
const path = require("path");
const CopyPlugin = require("copy-webpack-plugin");
module.exports = {
entry: {
popup: path.resolve(__dirname, "../src/index.tsx"),
background: path.resolve(__dirname, "../src/background.ts"),
},
plugins: [
new CopyPlugin({
patterns: [{ from: "public", to: "." }],
}),
],
module: {
rules: [
{
test: /\.(js|jsx)$/,
use: "babel-loader",
exclude: /node_modules/,
},
{
test: /\.ts(x)?$/,
loader: "ts-loader",
exclude: /node_modules/,
},
{
test: /\.png$/,
use: [
{
loader: "url-loader",
options: {
mimetype: "image/png",
},
},
],
},
],
},
resolve: {
extensions: [".js", ".jsx", ".ts", ".tsx"],
},
mode: "production",
output: {
path: path.resolve(__dirname, `../dist`),
filename: "[name].js",
},
};
Problem
I've tried redux-devtools-extension:
// src/index.tsx
import React from "react";
import ReactDOM from "react-dom";
import App from "./components/App";
import { Provider } from "react-redux";
import { createStore } from "redux";
import { composeWithDevTools } from "redux-devtools-extension";
import rootReducer from "./store/reducers";
export const store = createStore(rootReducer, composeWithDevTools());
ReactDOM.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>,
document.getElementById("root")
);
which shows:
I've also tried using remote-redux-devtools:
// src/index.tsx
import React from "react";
import ReactDOM from "react-dom";
import App from "./components/App";
import { Provider } from "react-redux";
import { createStore } from "redux";
import devToolsEnhancer from "remote-redux-devtools";
import rootReducer from "./store/reducers";
export const store = createStore(rootReducer, devToolsEnhancer());
ReactDOM.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>,
document.getElementById("root")
);
which seems more promising, but has no data in the store:
When I run in the browser, using npm start (react-scripts start), I do see the store in the Redux DevTools extension, so I am not sure what the problem is.
Possible Idea
When I build with React (react-scripts build), I can see the store just fine. The issue is that I cannot use react as it's build times are too slow and using webpack seems like the most logical alternative. Here is the build output:
Any ideas?
Note: this answer was originally added by OP as an edit to their original question, I have just reposted it as an answer.
A server needs to be running and remote redux devtools should be used rather than redux devtools extension.
The best approach would be the following:
Install npmjs.com/package/remotedev-server
Add "remotedev": "remotedev --hostname=localhost --port=8080" npm script
Run the above script to start a server
Right click on popup, Redux DevTools > Open Remote DevTools (not inspect)
Settings > Use Custom Local Server > Type in the hostname and port specified in the npm script.
Here is what my store looks like:
import { createStore } from "redux";
import { composeWithDevTools } from "remote-redux-devtools";
import rootReducer from "./store/reducers";
const composeEnhancers = composeWithDevTools({
realtime: true,
hostname: "localhost",
port: 8080
});
export const store = createStore(rootReducer, composeEnhancers());
ReactDOM.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>,
document.getElementById("root")
);
I think the problem is with webpack uglifying __REDUX_DEVTOOLS_EXTENSION_COMPOSE__ in the following code
You can try the following:
import { createStore, compose } from 'redux'
//same code as original but with bracket notation
const composeWithDevTools = (
typeof window !== 'undefined' && window["__REDUX_DEVTOOLS_EXTENSION_COMPOSE__"] ?
window["__REDUX_DEVTOOLS_EXTENSION_COMPOSE__"] :
function() {
if (arguments.length === 0) return undefined;
if (typeof arguments[0] === 'object') return compose;
return compose.apply(null, arguments);
}
);
//your original code but using your composeWithDevTools
export const store = createStore(rootReducer, composeWithDevTools());
You don't need to import composeWithDevTools from redux-devtools-extension as you've created it yourself but if this solves the problem you should create an issue requesting for bracket notation so uglify won't break the code.
To see what the compiled code is you can add a console log before your createStore: console.log("creating store") then you can disable source maps in chrome devtools (Command+Shift+P or Control+Shift+P) and then search for the console text creating store shortcut is: command+alt+f or control+shift+f)
i tried to setup a new Project with webpack, react and Typescript. Its not working.
Webpack is giving me this error:
ERROR in ./src/index.tsx 17:2
Module parse failed: Unexpected token (17:2)
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
ERROR
|
| ReactDOM.render(
> <StoreContext.Provider value={store}>
| <Router history={history}>
| <App />
# ./src/index.tsx 2:0-36 6:17-24 7:15-29
webpack.config.js
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const TerserWebpackPlugin = require('terser-webpack-plugin');
const isProd = process.env.NODE_ENV === 'production';
const config = {
mode: isProd ? 'production' : 'development',
entry: {
index: './src/index.tsx',
},
plugins: [
new HtmlWebpackPlugin({
title: 'Production',
}),
],
output: {
path: resolve(__dirname, 'dist'),
filename: '[name].js',
},
resolve: {
extensions: ['.js', '.jsx', '.ts', '.tsx'],
},
module: {
rules: [
{
test: /\.tsx?$/,
use: ['babel-loader', 'style-loader'],
exclude: /node_modules/,
},
],
},
};
if (isProd) {
config.optimization = {
minimizer: [
new TerserWebpackPlugin(),
],
};
} else {
config.devServer = {
port: 8080,
open: true,
hot: true,
compress: true,
stats: 'errors-only',
overlay: true,
};
}
module.exports = config;
package.json:
{
"scripts": {
"watch": "webpack --watch",
"start": "webpack serve --open",
"build": "webpack"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"#babel/cli": "^7.14.5",
"#babel/core": "^7.14.6",
"#babel/preset-env": "^7.14.7",
"#babel/preset-react": "^7.14.5",
"#babel/preset-typescript": "^7.14.5",
"#types/node": "^12.20.15",
"#types/react-datepicker": "^3.1.8",
"#types/react-dom": "^17.0.8",
"#types/uuid": "^8.3.0",
"#types/yup": "^0.29.11",
"#typescript-eslint/eslint-plugin": "^4.28.0",
"#typescript-eslint/parser": "^4.28.0",
"babel-loader": "^8.2.2",
"cross-env": "^7.0.3",
"css-loader": "^5.2.6",
"eslint": "^7.29.0",
"eslint-plugin-react": "^7.24.0",
"eslint-plugin-react-hooks": "^4.2.0",
"html-webpack-plugin": "^5.3.2",
"serve": "^12.0.0",
"style-loader": "^2.0.0",
"terser-webpack-plugin": "^5.1.3",
"ts-loader": "^9.2.3",
"ts-node": "^10.0.0",
"typescript": "^4.3.4",
"typings-for-css-modules-loader": "^1.7.0",
"webpack": "^5.40.0",
"webpack-cli": "^4.7.2",
"webpack-dev-server": "^3.11.2",
"webpack-merge": "^5.8.0",
"yup": "^0.32.9"
}
}
Index.tsx:
import ReactDOM from 'react-dom';
import './index.css';
import './app/layout/styles.css'
import App from './app/layout/App';
import reportWebVitals from './reportWebVitals';
import 'semantic-ui-css/semantic.min.css'
import {store, StoreContext } from './app/stores/store';
import {createBrowserHistory} from 'history';
import { Router} from "react-router-dom";
import 'react-toastify/dist/ReactToastify.min.css';
import 'react-datepicker/dist/react-datepicker.css';
export const history = createBrowserHistory();
ReactDOM.render(
<StoreContext.Provider value={store}>
<Router history={history}>
<App />
</Router>
</StoreContext.Provider>,
document.getElementById('root')
);
reportWebVitals();
I want to add tailwind to storybook. So that Stories will render just like it will render on web.
I used create-react-app project-name --template typescript to create the project.
Then to install the tailwind I followed this https://tailwindcss.com/docs/guides/create-react-app instruction from the documentation of tailwind.
Once I finished it I ran the code npm sb init. Which made sure that storybook ran.
Now I need to tell storybook to use tailwindcss for styling. But I have no idea how.
Every other answer I saw tells to edit postcss.config.js files.
But I followed this https://tailwindcss.com/docs/guides/create-react-app documentation where I didnt even have to create postcss.config.js file. So I am confused to what to do now.
For clarity I will include some configuration file below.
craco.config.js
module.exports = {
style: {
postcss: {
plugins: [
require('tailwindcss'),
require('autoprefixer'),
],
},
},
}
.storybook/preview.js
import "../src/index.css"
export const parameters = {
actions: { argTypesRegex: "^on[A-Z].*" },
}
.storybook/main.js
module.exports = {
"stories": [
"../src/**/*.stories.mdx",
"../src/**/*.stories.#(js|jsx|ts|tsx)"
],
"addons": [
"#storybook/addon-links",
"#storybook/addon-essentials",
"#storybook/preset-create-react-app"
]
}
src/index.css
#tailwind base;
#tailwind components;
#tailwind utilities;
tailwind.config.js
module.exports = {
purge: ['./src/**/*.{js,jsx,ts,tsx}', './public/index.html'],
darkMode: false, // or 'media' or 'class'
theme: {
extend: {},
},
variants: {
extend: {},
},
plugins: [],
}
package.json
`{
"name": "memory",
"version": "0.1.0",
"private": true,
"dependencies": {
"#craco/craco": "^6.0.0",
"#tailwindcss/postcss7-compat": "^2.0.2",
"#testing-library/jest-dom": "^5.11.4",
"#testing-library/react": "^11.1.0",
"#testing-library/user-event": "^12.1.10",
"#types/jest": "^26.0.15",
"#types/node": "^12.0.0",
"#types/react": "^16.14.2",
"#types/react-dom": "^16.9.8",
"autoprefixer": "^9.8.6",
"postcss": "^7.0.35",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-scripts": "4.0.1",
"tailwindcss": "npm:#tailwindcss/postcss7-compat#^2.0.2",
"typescript": "^4.0.3",
"web-vitals": "^0.2.4"
},
"scripts": {
"start": "craco start",
"build": "craco build",
"test": "craco test",
"eject": "react-scripts eject",
"storybook": "start-storybook -p 6006 -s public",
"build-storybook": "build-storybook -s public"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"#storybook/addon-actions": "^6.1.11",
"#storybook/addon-essentials": "^6.1.11",
"#storybook/addon-links": "^6.1.11",
"#storybook/node-logger": "^6.1.11",
"#storybook/preset-create-react-app": "^3.1.5",
"#storybook/react": "^6.1.11"
}
}
tsconfig.json
{
"compilerOptions": {
"target": "es5",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noFallthroughCasesInSwitch": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx"
},
"include": [
"src"
]
}
Storybook recommends using the #storybook/addon-postcss for customizing the postCSS config from now on (instead of relying on customizing the postcss-loader):
Add the postCSS addon to your installation
npm i -D #storybook/addon-postcss # or
yarn add -D #storybook/addon-postcss
Create the postcss.config.js in the project root
// postcss.config.js
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
}
}
Add the plugin to your .storybook/main.js
// .storybook/main.js
module.exports = {
...
addons: [
...
{
name: '#storybook/addon-postcss',
options: {
cssLoaderOptions: {
// When you have splitted your css over multiple files
// and use #import('./other-styles.css')
importLoaders: 1,
},
postcssLoaderOptions: {
// When using postCSS 8
implementation: require('postcss'),
},
},
},
],
};
Import your css file in the .storybook/preview.js
// .storybook/preview.js
import '../src/styles.css';
You're almost there.
The missing piece of your config is to add a webpack configuration to apply tailwind to postcss-loader:
const path = require('path')
module.exports = {
stories: [
'../src/**/*.stories.mdx',
'../src/**/*.stories.#(js|jsx|ts|tsx)'
],
addons: [
'#storybook/addon-links',
'#storybook/addon-essentials',
'#storybook/preset-create-react-app',
],
webpackFinal: async (config) => {
config.module.rules.push({
test: /\.css$/,
use: [
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [
require('tailwindcss'),
require('autoprefixer'),
],
},
},
},
],
include: path.resolve(__dirname, '../'),
})
return config
},
}
TAILWIND STORYBOOK CRA [2022-2023(hopefully)]
package.json
"devDependencies": {
"#storybook/addon-actions": "^6.5.9",
"#storybook/addon-essentials": "^6.5.9",
"#storybook/addon-interactions": "^6.5.9",
"#storybook/addon-links": "^6.5.9",
"#storybook/addon-postcss": "^2.0.0",
"#storybook/builder-webpack5": "^6.5.9",
"#storybook/manager-webpack5": "^6.5.9",
"#storybook/node-logger": "^6.5.9",
"#storybook/preset-create-react-app": "^4.1.2",
"#storybook/react": "^6.5.9",
"#storybook/testing-library": "^0.0.13",
"#typescript-eslint/eslint-plugin": "^5.28.0",
"#typescript-eslint/parser": "^5.28.0",
"autoprefixer": "^10.4.7",
"babel-plugin-named-exports-order": "^0.0.2",
"eslint": "^8.17.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-jsx-a11y": "^6.5.1",
"eslint-plugin-react": "^7.30.0",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-simple-import-sort": "^7.0.0",
"postcss": "^8.4.14",
"tailwindcss": "^3.1.1",
"webpack": "^5.73.0"
}
tailwind.config.js
module.exports = {
content: [
"./src/**/*.{js,jsx,ts,tsx}",
],
theme: {
extend: {},
},
plugins: [],
}
postcss.config.js
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}
.storybook/main.js
module.exports = {
stories: [
"../src/**/*.stories.mdx",
"../src/**/*.stories.#(js|jsx|ts|tsx)"
],
addons: [
"#storybook/addon-links",
"#storybook/addon-essentials",
"#storybook/addon-interactions",
"#storybook/preset-create-react-app",
{
name: '#storybook/addon-postcss',
options: {
postcssLoaderOptions: {
implementation: require('postcss'),
},
},
},
],
framework: "#storybook/react",
core: {
"builder": "#storybook/builder-webpack5"
}
}
.storybook/preview.js
import '!style-loader!css-loader!postcss-loader!tailwindcss/tailwind.css';
export const parameters = {
actions: { argTypesRegex: "^on[A-Z].*" },
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/,
},
},
}
The answer was right but in the latest CRA I have to config like this:
config.module.rules.push({
test: /\.css$/,
use: [
{
loader: "postcss-loader",
options: {
// HERE: OPTIONS
postcssOptions: {
plugins: [require("tailwindcss"), require("autoprefixer")],
},
},
},
],
include: path.resolve(__dirname, "../"),
});
Similar to ofhouse's answer, but here is a solution if you don't want to have an extra postcss.config.js for only a few lines or if you want use typescript in everything (as the loader doesn't pick up postcss.config.ts)
Add the official postCSS addon
npm i -D #storybook/addon-postcss
yarn add -D #storybook/addon-postcss
Config main.ts & tailwind.config.ts
/* .stories/main.ts */
import postcss from 'postcss';
import * as tailwindcss from '../tailwind.config';
import type { StorybookConfig } from '#storybook/react/types';
export const addons: StorybookConfig['addons'] = [
// other addons,
{
name: '#storybook/addon-postcss',
options: {
postcssLoaderOptions: {
implementation: postcss,
postcssOptions: {
plugins: {
tailwindcss, // or you can nest your options entirely here
autoprefixer: {
// autoprefixer options
},
},
},
},
},
},
];
/* tailwind.config.ts */
import type { TailwindConfig } from 'tailwindcss/tailwind-config';
export const theme: TailwindConfig['theme'] = {
// theme options
}
// other options
This problem gave me headaches too. I followed every solution that can be found on StackOverflow and Github.
But I only could "fix it" by running the tailwind-CLI and building the global.css file and importing it to ./storybook/preview.js
here's the cli command used.
npx tailwindcss -i ./src/styles/global.css -o ./.storybook/global.css --watch
then import it from the output path (-o flag) in the command above.
// ./storybook/preview.js
import './global.css';
...
I've tried all the above answers but unfortunately, I was still getting some weird unknown word error when running the storybook.
This is the only solution that worked for me:
https://github.com/storybookjs/addon-postcss/issues/33#issuecomment-1173042151
I created an app using create-react-app and started to use webpack and babel.
What I get from this code is that I cannot render my components (example, <App />).
I can only render elements like h1 or h2, even if I import App in index.js (and don't use it), I cannot see anything.
I run with npm run dev-server.
webpack.config.js:
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
path: path.join(__dirname, 'public'),
filename: 'bundle.js'
},
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
options: {
presets: ['#babel/react']
}
}
]
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
}
]
},
devtool: 'cheap-module-eval-source-map',
devServer: {
contentBase: path.join(__dirname, 'public')
}
};
index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import './style.css';
ReactDOM.render(
<App />,
document.getElementById('root')
);
App.js:
import React, { Component } from 'react';
class App extends Component {
render() {
return (
<div className="mainContainer">
<h1>Test h1</h1>
<h2>Test h2</h2>
<p>Test p</p>
</div>
);
}
}
export default App;
package.json:
{
"name": "smartpharma-front",
"version": "0.0.1",
"private": true,
"dependencies": {
"axios": "^0.19.0",
"react": "^16.12.0",
"react-dom": "^16.12.0",
"react-scripts": "^3.3.0"
},
"scripts": {
"start": "webpack --mode=development",
"build": "webpack --mode=production",
"dev-server": "webpack-dev-server",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"engines": {
"node": "13.3.0",
"npm": "6.13.1"
},
"devDependencies": {
"#babel/core": "^7.7.7",
"#babel/preset-env": "^7.7.7",
"#babel/preset-react": "^7.7.4",
"babel-loader": "^8.0.6",
"css-loader": "^3.4.0",
"style-loader": "^1.1.1",
"webpack": "^4.41.4",
"webpack-cli": "^3.3.10"
},
"description": "SmartPharma Frontend",
"main": "webpack.config.js",
"repository": {
"type": "git",
"url": "git+https://github.com/vfeder6/smartpharma-front.git"
},
"keywords": [],
"author": "",
"license": "ISC",
"bugs": {
"url": "https://github.com/vfeder6/smartpharma-front/issues"
},
"homepage": "https://github.com/vfeder6/smartpharma-front#readme"
}
I'm trying to set up Jest to test my app as it grows. I'm getting the below error:
SyntaxError: Unexpected identifier
> 1 | const screenSize = require("../src/index.js").screenSize;
| ^
I'm using Phaser 3, Webpack, Babel, and React.
I'm relatively new to all except React.
I followed Jest's Getting Started tutorial and using with webpack tutorial, but I'm still getting the error.
package.json
{
"name": "phaser3-project-template",
"version": "1.1.0",
"description": "A Phaser 3 Project Template",
"main": "src/index.js",
"scripts": {
"build": "webpack --config webpack/prod.js ",
"start": "webpack-dev-server --config webpack/base.js --open",
"test": "jest"
},
"repository": {
"type": "git",
"url": "git+https://github.com/photonstorm/phaser3-project-template.git"
},
"author": "Richard Davey <rdavey#gmail.com> (http://www.photonstorm.com)",
"license": "MIT",
"licenseUrl": "http://www.opensource.org/licenses/mit-license.php",
"bugs": {
"url": "https://github.com/photonstorm/phaser3-project-template/issues"
},
"homepage": "https://github.com/photonstorm/phaser3-project-template#readme",
"devDependencies": {
"#babel/core": "^7.4.3",
"#babel/plugin-proposal-class-properties": "^7.4.0",
"#babel/preset-env": "^7.4.3",
"#babel/preset-react": "^7.0.0",
"babel-jest": "^24.7.1",
"babel-loader": "^8.0.5",
"clean-webpack-plugin": "^1.0.0",
"file-loader": "^3.0.1",
"html-webpack-plugin": "^3.2.0",
"jest": "^24.7.1",
"path": "^0.12.7",
"raw-loader": "^1.0.0",
"react": "^16.8.6",
"react-dom": "^16.8.6",
"terser-webpack-plugin": "^1.2.1",
"webpack": "^4.28.3",
"webpack-cli": "^3.2.1",
"webpack-dev-server": "^3.1.14",
"webpack-merge": "^4.2.1"
},
"dependencies": {
"babel-core": "^6.26.3",
"babel-preset-es2015": "^6.24.1",
"babel-preset-react": "^6.24.1",
"css-loader": "^2.1.1",
"phaser": "^3.16.2",
"react-redux": "^7.0.2",
"redux": "^4.0.1",
"redux-thunk": "^2.3.0",
"style-loader": "^0.23.1"
},
"jest": {
"modulePaths": [
"node_modules"
],
"moduleFileExtensions": [
"js",
"jsx"
],
"moduleDirectories": [
"node_modules"
],
"moduleNameMapper": {
"\\.(css|less)$": "<rootDir>/__mocks__/styleMock.js",
"\\.(gif|ttf|eot|svg)$": "<rootDir>/__mocks__/fileMock.js"
}
}
}
webpack/base.js
const webpack = require("webpack");
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const CleanWebpackPlugin = require("clean-webpack-plugin");
module.exports = {
mode: "development",
devtool: "eval-source-map",
entry: "./src/index.js", //do we need this?
output: {
path: path.resolve("dist"),
filename: "index_bundle.js"
},
module: {
rules: [
{
test: /\.css$/,
use: [{ loader: "style-loader" }, { loader: "css-loader" }]
},
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.jsx?$/,
exclude: /node_modules/,
use: "babel-loader"
},
{
test: [/\.vert$/, /\.frag$/],
use: "raw-loader"
},
{
test: /\.(gif|png|jpe?g|svg|xml)$/i,
use: "file-loader"
}
]
},
plugins: [
new CleanWebpackPlugin(["dist"], {
root: path.resolve(__dirname, "../")
}),
new webpack.DefinePlugin({
CANVAS_RENDERER: JSON.stringify(true),
WEBGL_RENDERER: JSON.stringify(true)
}),
new HtmlWebpackPlugin({
template: "./index.html",
filename: "index.html",
inject: "body"
})
]
};
.babelrc.js
const presets = [
[
"#babel/env",
{
targets: {
browsers: [">0.25%", "not ie 11", "not op_mini all"],
node: "current"
},
modules: false
}
],
"#babel/preset-react"
];
const plugins = ["#babel/plugin-proposal-class-properties"];
module.exports = { presets, plugins };
jest.config.js
"use strict";
module.exports = {
testMatch: ["<rootDir>/**/*.test.js"],
testPathIgnorePatterns: ["/src/", "node_modules"]
};
index.test.js
const screenSize = require("../src/index.js").screenSize;
//import toBeType from "jest-tobetype";
console.log(screenSize);
test("screenSize is an object", () => {
expect(typeof screenSize).toBe("object");
});
Github Repo
How can I get Jest to process the es6 syntax?
Require is a node environment syntax for importing variables, and Jest runs in node. More background on the differences between import/require and node can be seen in this SO question
You can add support for this with
npm install --save-dev #babel/plugin-proposal-class-properties #babel/plugin-transform-modules-commonjs
and include these as presets in your babelrc.js
const presets = [
[
"#babel/env",
{
targets: {
browsers: [">0.25%", "not ie 11", "not op_mini all"]
},
modules: false
}
],
"#babel/preset-react"
];
const plugins = [
"#babel/plugin-proposal-class-properties",
"#babel/plugin-transform-modules-commonjs"
];
module.exports = { presets, plugins };
The above code will still run into a number of errors details to resolve those can be seen here: https://medium.com/#Tnodes/setting-up-jest-with-react-and-phaser-422b174ec87e