I keep getting this error:
src/legacy/widgetlib.tsx → dist/withReact16/browser.js...
{
code: 'MISSING_NODE_BUILTINS',
message: "Creating a browser bundle that depends on Node.js built-in module ('punycode'). You might need to include https://www.npmjs.com/package/rollup-plugin-node-builtins",
modules: [ 'punycode' ],
toString: [Function]
}
I have included rollup-plugin-node-builtins in multiple different ways and I've googled all over the place. Every "solution" I've found seems to basically be the same thing, but it isn't working for me. I am also not even directly using punycode. Two of my dependencies have it as a dependency. I am using twitter-text lib and oauth-signature. If I comment out those two imports I no longer get this problem. Here is my complete rollup.config.js file:
import resolve from '#rollup/plugin-node-resolve';
import postcss from 'rollup-plugin-postcss';
import commonjs from '#rollup/plugin-commonjs';
import babel from 'rollup-plugin-babel';
import json from '#rollup/plugin-json';
import image from '#rollup/plugin-image';
import replace from 'rollup-plugin-replace';
import gzipPlugin from 'rollup-plugin-gzip';
import { terser } from 'rollup-plugin-terser';
import includePaths from 'rollup-plugin-includepaths';
import builtins from 'rollup-plugin-node-builtins';
import globals from 'rollup-plugin-node-globals';
import React from 'react';
import ReactDOM from 'react-dom';
const extensions = ['.js', '.jsx', '.ts', '.tsx'];
const { PRODUCTION } = process.env;
const CODES = [
'THIS_IS_UNDEFINED',
'MISSING_GLOBAL_NAME',
'CIRCULAR_DEPENDENCY',
];
const globalVars = {
react: 'React',
'react-dom': 'ReactDOM',
};
const discardWarning = warning => {
if (CODES.includes(warning.code)) {
return;
}
// eslint-disable-next-line no-console
console.error(warning);
};
const commonConfig = {
onwarn: discardWarning,
plugins: [
replace({
'process.env.NODE_ENV': JSON.stringify(
PRODUCTION ? 'production' : 'development'
),
}),
image(),
globals(),
builtins(),
resolve({
jsnext: true,
extensions,
preferBuiltins: true,
browser: true,
mainFields: ['browser', 'jsnext', 'module', 'main'],
}),
includePaths({
paths: ['src'],
extensions: [...extensions, '.scss', '.json'],
}),
commonjs({
include: 'node_modules/**',
namedExports: {
react: Object.keys(React),
'react-dom': Object.keys(ReactDOM),
},
}),
babel({
extensions,
runtimeHelpers: true,
babelrc: true,
exclude: 'node_modules/**',
}),
json(),
postcss({
plugins: [],
}),
terser(),
],
};
const browserLibWithReact16 = {
...commonConfig,
input: 'src/legacy/widgetlib.tsx',
output: {
format: 'iife',
sourcemap: true,
name: 'WLIB',
file: 'dist/withReact16/browser.js',
},
plugins: [...commonConfig.plugins, gzipPlugin()],
};
const npmWLIBWithReact16 = {
...commonConfig,
input: 'src/widgetlib.tsx',
output: {
file: 'dist/withReact16/WLIB.js',
format: 'esm',
sourcemap: true,
},
};
const npmLibNoReact = {
...commonConfig,
external: Object.keys(globalVars),
input: 'src/widgetlib.tsx',
output: {
file: 'dist/index.js',
format: 'esm',
sourcemap: true,
},
};
export default [npmLibNoReact, npmWLIBWithReact16, browserLibWithReact16];
The error is only happening for the browserLibWithReact16 config.
Any help would be appreciated.
Related
What I try to achieve
I'm trying to create a little library for private use - basically just splitting up some code into lib (product) and app (project) code.
All my source code lives in /src folder which contains React, TypeScript and SCSS code. It would be great, if I can use the SCSS imports directly in React like: import './_button.scss';
I have another SCSS file: src/style/_main.scss it includes some mixins, global styles, resets etc.
Config files
import commonjs from '#rollup/plugin-commonjs';
import json from '#rollup/plugin-json';
import resolve from '#rollup/plugin-node-resolve';
import terser from '#rollup/plugin-terser';
import typescript from '#rollup/plugin-typescript';
import url from '#rollup/plugin-url';
import dts from 'rollup-plugin-dts';
import scss from 'rollup-plugin-scss';
import { format, parse } from 'path';
import pkg from './package.json' assert { type: 'json' };
const getTypesPath = (jsFile) => {
const pathInfo = parse(jsFile);
return format({
...pathInfo,
base: '',
dir: `${pathInfo.dir}/types`,
ext: '.d.ts',
});
};
export default [
{
input: 'src/index.ts',
output: [
{
file: pkg.main,
format: 'cjs',
interop: 'compat',
exports: 'named',
sourcemap: true,
inlineDynamicImports: true,
},
{
file: pkg.module,
format: 'esm',
exports: 'named',
sourcemap: true,
inlineDynamicImports: true,
},
],
plugins: [
resolve({ browser: true }),
commonjs({ extensions: ['.js', '.jsx', '.ts', '.tsx'] }),
typescript({ tsconfig: './tsconfig.build.json' }),
url(),
scss({
failOnError: true
}),
json(),
terser(),
],
external: ['react', 'react-dom'],
},
{
input: getTypesPath(pkg.module ?? pkg.main),
output: [{ file: pkg.types, format: 'esm' }],
plugins: [dts()],
},
];
My tsconfig.build.json looks like this:
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./types",
"declaration": true,
"declarationDir": "./types",
"allowSyntheticDefaultImports": true
}
}
Where I struggle
The main issue right now is, that it imports my SCSS file in the definition file e.g. button.d.ts looks like:
import type { FunctionComponent } from 'react';
import type { IButtonProps } from './button.type';
import './_button.scss';
export declare const Button: FunctionComponent<IButtonProps>;
[!] RollupError: Could not resolve "./_button.scss" from "build/esm/types/button/button.d.ts"
Which is indeed a problem, but how can I fix it?
I also get the error:
Error:
#use rules must be written before any other rules.
╷
4 │ #use 'src/style/util/mixin';
│ ^^^^^^^^^^^^^^^^^^^^^^^^^^^
╵
stdin 4:1 root stylesheet
But it does not really make a lot of sense, since my _button.scss partial has this written on the first line.
My Question
How do I make it work so that I can use SCSS in my library? The best case would be that I don't have to touch my original code. I just want to transpile/bundle it so I can use it somewhere else. Any advice?
After hours of probing, I finally made it work.
The issue was, that it bundled all my sass styles and it did not take into account, that I am using the new #use module syntax. Because everything got concatenated into one big file, #use syntax got placed in the middle of the file resulting in an error. Apparently, only the old #import syntax is properly supported by rollup-plugin-scss - or I was just too incapable of making it work.
So I switched to the https://anidetrix.github.io/rollup-plugin-styles/
library to process the files. All I had to do is to use the styles plugin and I set mode: 'inject' it then injected the styles into my [esm|cjs]/index.js file. Upon importing the lib in the app and starting it, the styles got applied.
Besides, I also had to externalize the imports from the index.d.ts.
The updated config file:
import commonjs from '#rollup/plugin-commonjs';
import json from '#rollup/plugin-json';
import resolve from '#rollup/plugin-node-resolve';
import terser from '#rollup/plugin-terser';
import typescript from '#rollup/plugin-typescript';
import url from '#rollup/plugin-url';
import { format, parse } from 'path';
import dts from 'rollup-plugin-dts';
import external from 'rollup-plugin-peer-deps-external';
import styles from 'rollup-plugin-styles';
import pkg from './package.json' assert { type: 'json' };
const getTypesPath = (jsFile) => {
const pathInfo = parse(jsFile);
return format({
...pathInfo,
base: '',
dir: `${pathInfo.dir}/types`,
ext: '.d.ts',
});
};
export default [
{
input: 'src/index.ts',
output: [
{
file: pkg.main,
format: 'cjs',
interop: 'compat',
exports: 'named',
sourcemap: true,
inlineDynamicImports: true,
},
{
file: pkg.module,
format: 'esm',
exports: 'named',
sourcemap: true,
inlineDynamicImports: true,
},
],
external: ['react', 'react-dom'],
plugins: [
external(),
resolve({
browser: true,
}),
url(),
styles({
mode: 'inject'
}),
json(),
commonjs({
extensions: ['.js', '.jsx', '.ts', '.tsx'],
}),
typescript({
tsconfig: './tsconfig.build.json',
}),
terser(),
],
},
{
input: getTypesPath(pkg.module ?? pkg.main),
output: [
{
file: pkg.types,
format: 'esm',
},
],
external: [/\.(sass|scss|css)$/] /* ignore style files */,
plugins: [dts()],
},
];
I've been working on a custom rollup config which takes a React project, and inlines the js and css in index.html.
When I've imported some third party react libraries (like material-ui-color) I run into a problem with CommonJS where it says there's a syntax error. Of the libraries I've tried to install so far, the word 'process' is most commonly the word it breaks on. Here is the log from the material-ui-color issue:
[!] (plugin commonjs) SyntaxError: Unexpected token (205:28) in /Users/meyerm/Documents/GitHub/button-generator-figma-plugin/node_modules/jss/dist/jss.esm.js
node_modules/jss/dist/jss.esm.js (205:28)
203: var newValue = value;
204:
205: if (!options || options.process !== false) {
^
I've included the rollup-plugin-replace to fix any occurrences of process.env.NODE_ENV but this seems to be a different issue.
Here is my rollup config:
import resolve from '#rollup/plugin-node-resolve';
import commonjs from '#rollup/plugin-commonjs';
import babel from '#rollup/plugin-babel';
import livereload from 'rollup-plugin-livereload';
import replace from '#rollup/plugin-replace';
import { terser } from 'rollup-plugin-terser';
import postcss from 'rollup-plugin-postcss';
import html from 'rollup-plugin-bundle-html-plus';
import typescript from 'rollup-plugin-typescript';
import svgr from '#svgr/rollup';
const production = !process.env.ROLLUP_WATCH;
export default [
/*
Transpiling React code and injecting into index.html for Figma
*/
{
input: 'src/app/index.tsx',
output: {
name: 'ui',
file: 'dist/bundle.js',
format: 'umd',
},
plugins: [
// What extensions is rollup looking for
resolve({
extensions: ['.jsx', '.js', '.json', '.ts', '.tsx'],
}),
// Manage process.env
replace({
preventAssignment: true,
process: JSON.stringify({
env: {
isProd: production,
},
}),
'process.env.NODE_ENV': JSON.stringify(production),
}),
typescript({ sourceMap: !production }),
// Babel config to support React
babel({
presets: ['#babel/preset-react', '#babel/preset-env'],
babelHelpers: 'runtime',
plugins: ['#babel/plugin-transform-runtime'],
extensions: ['.js', '.ts', 'tsx', 'jsx'],
compact: true,
exclude: 'node_modules/**',
}),
commonjs({
include: 'node_modules/**',
}),
svgr(),
// Config to allow sass and css modules
postcss({
extensions: ['.css, .scss, .sass'],
modules: true,
use: ['sass'],
}),
// Injecting UI code into ui.html
html({
template: 'src/app/index.html',
dest: 'dist',
filename: 'index.html',
inline: true,
inject: 'body',
ignore: /code.js/,
}),
// If dev mode, serve and livereload
!production && serve(),
!production && livereload('dist'),
// If prod mode, minify
production && terser(),
],
watch: {
clearScreen: true,
},
},
/*
Main Figma plugin code
*/
{
input: 'src/plugin/controller.ts',
output: {
file: 'dist/code.js',
format: 'iife',
name: 'code',
},
plugins: [resolve(), typescript(), commonjs({ transformMixedEsModules: true }), production && terser()],
},
];
function serve() {
let started = false;
return {
writeBundle() {
if (!started) {
started = true;
// Start localhost dev server on port 5000 to work on the UI in the browser
require('child_process').spawn('npm', ['run', 'start', '--', '--dev'], {
stdio: ['ignore', 'inherit', 'inherit'],
shell: true,
});
}
},
};
}
Any ideas how I can overcome this and import 3rd party libraries into the project easily?
I recommend rewriting the config in the following way:
replace({
"process.env.isProd": production,
}),
I am getting an error: Hooks can only be called inside the body of a function componen
On image you can see that I am using function component: http://prntscr.com/rgk36s
My code is bundled using rollup.
What is wrong?
My rollup config is:
import { readdirSync } from 'fs';
import path from 'path';
import babel from 'rollup-plugin-babel';
import commonjs from 'rollup-plugin-commonjs';
import external from 'rollup-plugin-peer-deps-external';
import pkg from './package.json';
import replace from 'rollup-plugin-replace';
import resolve from 'rollup-plugin-node-resolve';
import { terser } from 'rollup-plugin-terser';
const EXTENSIONS = ['.ts', '.tsx', '.js', '.jsx', '.json'];
const CODES = [
'THIS_IS_UNDEFINED',
'MISSING_GLOBAL_NAME',
'CIRCULAR_DEPENDENCY',
];
const getChunks = URI =>
readdirSync(path.resolve(URI))
.filter(x => x.includes('.js'))
.reduce((a, c) => ({ ...a, [c.replace('.js', '')]: `src/${c}` }), {});
const discardWarning = warning => {
if (CODES.includes(warning.code)) {
return;
}
console.error(warning);
};
const env = process.env.NODE_ENV;
const commonPlugins = () => [
external({
includeDependencies: true,
}),
babel({
babelrc: false,
presets: [['#babel/preset-env', { modules: false }], '#babel/preset-react'],
extensions: EXTENSIONS,
exclude: 'node_modules/**',
}),
commonjs({
include: /node_modules/,
}),
replace({ 'process.env.NODE_ENV': JSON.stringify(env) }),
resolve({
extensions: EXTENSIONS,
preferBuiltins: false,
}),
];
export default [
{
onwarn: discardWarning,
input: 'src/index.js',
output: {
esModule: false,
file: pkg.unpkg,
format: 'umd',
name: 'myLibrary',
exports: 'named',
globals: {
react: 'React',
'react-dom': 'ReactDOM',
'styled-components': 'styled',
},
},
plugins: [...commonPlugins(), env === 'production' && terser()],
},
{
onwarn: discardWarning,
input: getChunks('src'),
output: [
{ dir: 'esm', format: 'esm', sourcemap: true },
{ dir: 'cjs', format: 'cjs', exports: 'named', sourcemap: true },
],
plugins: commonPlugins(),
},
];
I don't know what is wrong, can you help me to solve my problem? Looks like that react is not bundled with code.
I am trying to build my react library
My component is simple:
import React, {useState} from 'react';
const Bar = () => {
const [value, setValue] = useState(0)
return (
<button onClick={() => setValue(value + 1)}>
{value}
</button>
)
}
export default Bar
exported by index file : export { default as Bar } from './Bar';
And usage of my component in react-create-app:
import * as React from 'react';
import './App.css';
import {Bar} from 'my-library';
function App () {
return (
<div className="App">
<hr />
<Bar />
</div>
);
}
export default App;
I got a project that is compiled with webpack and everything works well, but we are moving to rollupJS and i'm stuked with a file that is imported.
utils/init-jquery.jsx:
global.$ = global.jQuery = require('jquery');
require('jquery-mask-plugin');
require('fancybox')(global.$);
require('libraries/jquery.unserialize');
This file is imported for example in this file app.jsx:
import React from 'react';
import { render } from 'react-dom';
import InitJquery from 'common/utils/init-jquery';
import Init from 'common/utils/init';
...
I got stuked with this error in the console chrome:
Uncaught ReferenceError: global is not defined(…)
my rollup config:
var multiEntry = require('rollup-plugin-multi-entry');
var babel = require('rollup-plugin-babel');
var uglify = require('rollup-plugin-uglify');
var rollupIncludePaths = require('rollup-plugin-includepaths');
var nodeResolve = require( 'rollup-plugin-node-resolve');
var commonjs = require( 'rollup-plugin-commonjs');
var replace = require( 'rollup-plugin-replace');
const includePathOptions = {
paths: ['target/scripts'],
extensions: ['.jsx','.js']
};
var cache;
module.exports = function(grunt) {
return {
options: {
plugins: function () {
return [
rollupIncludePaths(includePathOptions),
replace({
'process.env.NODE_ENV': JSON.stringify( 'production' )
}),
nodeResolve({ jsnext: true, main: true }),
commonjs({
// extensions: [ '.js' ],
sourceMap: true,
//include: 'target/scripts/common/utils',
//ignoreGlobal: true,
namedExports: {
// left-hand side can be an absolute path, a path
// relative to the current directory, or the name
// of a module in node_modules
'formsy-react': [ 'Form', 'Mixin' ],
'react-dom': [ 'render' ],
'react': [ 'Component' ]
}
}),
babel({
babelrc: false,
presets: [["es2015",{modules:false}], "react"],
exclude: ['*/__tests__/**/*', './node_modules/**/*'],
plugins: ["external-helpers"]
}),
uglify()
];
},
cache:cache,
sourceMap: true,
format: 'cjs',
},
main: {
dest: './target/scripts/checkout/cart.bundle.js',
src: './target/scripts/checkout/cart/app-cart.jsx', // Only one source file is permitted
}
};
};
I've been using css-modules with mocha, enzyme and css-modules-require-hook without any problems.
Foo.js
import React from 'react';
import styles from './Foo.css';
const Foo = () => <div className={ styles.foo }>Foo component</div>;
export default Foo;
Foo.css
.foo {
color: rebeccapurple;
}
Foo.test.js
import Foo from './Foo';
describe('<Foo />', () => {
it('should render proper markup', () => {
const wrapper = shallow(<Foo />);
expect(wrapper.find('.foo')).to.have.length(1);
});
});
I started using Karma with karma-webpack-with-fast-source-maps and now the test fails because the styles in Foo.js is an array and it's not using keys to keep original class name.
[[376, '.Foo__foo___3QT3e {
color: rebeccapurple;
}
', '']]
I've tried importing the css-modules-require-hook in test-bundler.js for karma-webpack but that throws a bunch of errors.
WARNING in ./~/css-modules-require-hook/preset.js
Critical dependencies:
13:7-22 the request of a dependency is an expression
# ./~/css-modules-require-hook/preset.js 13:7-22
// many more warnings
ERROR in ./~/css-modules-require-hook/lib/index.js
Module not found: Error: Cannot resolve module 'fs' in /Users/qmmr/code/streetlife/composer/code/site/node_modules/css-modules-require-hook/lib
# ./~/css-modules-require-hook/lib/index.js 14:19-32
// more errors
PhantomJS 2.1.1 (Mac OS X 0.0.0) ERROR
SyntaxError: Unexpected token ')'
webpack.config.test.js
/* eslint-disable */
var path = require('path');
const CSS_MODULES_LOADER = [
'modules',
'importLoaders=1',
'localIdentName=[name]__[local]___[hash:base64:5]'
].join('&');
module.exports = {
resolve: {
extensions: [ '', '.js' ],
},
devtool: 'inline-source-map',
module: {
loaders: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel',
query: {
cacheDirectory: true,
plugins: [ 'transform-runtime', 'transform-class-properties', 'transform-export-extensions' ],
presets: [ 'es2015', 'react', 'stage-2' ],
}
},
{
test: /\.css$/,
loader: `css?${ CSS_MODULES_LOADER }`,
include: path.join(__dirname, '/css/modules'),
},
{ test: /\.json$/, loader: 'json' },
],
},
externals: {
'cheerio': 'window',
'react/addons': true,
'react/lib/ExecutionEnvironment': true,
'react/lib/ReactContext': true
},
};
karma.conf.js
// Karma configuration
var webpackConfig = require('./webpack.config.test');
module.exports = function(config) {
config.set({
basePath: '',
frameworks: [ 'mocha' ],
plugins: [
'karma-mocha',
'karma-phantomjs-launcher',
'karma-webpack-with-fast-source-maps'
],
files: [
{
pattern: './testBundler.js',
watched: false,
served: true,
included: true,
},
],
exclude: [],
preprocessors: {
[ './test-bundler.js' ]: [ 'webpack' ]
},
webpack: webpackConfig,
webpackMiddleware: {
noInfo: true,
stats: 'errors-only',
},
reporters: ['progress'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: [ 'PhantomJS' ],
singleRun: true,
concurrency: Infinity,
})
}
test-bundler.js
// ---------------------------------------
// Test Environment Setup
// ---------------------------------------
import React from 'react';
import chai from 'chai';
import sinon from 'sinon';
import { shallow, mount } from 'enzyme';
// require('css-modules-require-hook/preset'); // Fix css-modules not rendering in tests
global.React = React;
global.expect = chai.expect;
global.sinon = sinon;
global.shallow = shallow;
global.mount = mount;
// ---------------------------------------
// Require Tests
// ---------------------------------------
// for use with karma-webpack-with-fast-source-maps
const __karmaWebpackManifest__ = new Array(); // eslint-disable-line
const inManifest = (path) => ~__karmaWebpackManifest__.indexOf(path);
const testsContext = require.context('../react', true, /\.test\.js$/);
// only run tests that have changed after the first pass.
const testsToRun = testsContext.keys().filter(inManifest);
(testsToRun.length ? testsToRun : testsContext.keys()).forEach(testsContext);
How can I use css-modules-require-hook in my setup (karma + webpack)?
EDIT: I've created a repository https://github.com/qmmr/yab to show the issue. When running npm run test:mocha the test passes. When running npm run test it fails (this is the karma-webpack integration).