Rollup.js: undefined objects in external dependencies - javascript

I recently started playing with rollupjs. After configuring everything as per available docs and bundling things up, I got many errors from my external libraries about undefined objects. This sort of errors: Cannot read property 'parse' of undefined coming from crypto-js.
It complains about this line in the code: var ciphertext = Base64.parse(openSSLStr). So Base64 is undefined. I have few errors like this from different external libraries bundled in.
I use a handful of external dependencies:
chart.js,
crypto-js,
mithril,
moment,
pluralize
All of them work perfectly with jspm. I decided to try rollup to speed things up as jspm is soooo slow at the moment. Now half of my external dependencies stopped working. I get "undefined things" and "...not a function" kind of errors coming from external libraries only.
What could possibly be the cause of it?
This is my rollup.config.js
import babel from 'rollup-plugin-babel';
import npm from 'rollup-plugin-npm';
import commonjs from 'rollup-plugin-commonjs';
import uglify from 'rollup-plugin-uglify';
export default {
entry: 'app/scripts/application/main.js',
format: 'cjs',
plugins: [
npm({
jsnext: true,
main: true,
}),
babel({
exclude: 'node_modules/**',
presets: [ 'es2015-rollup' ],
}),
commonjs(),
uglify(),
],
dest: 'static/js/application.js',
};
Let me know if any other details are needed.
Thanks.
EDIT
I've done a simple tests-reproduction bundling those libraries that generate errors in my application.
package.json
{
"name": "minion",
"private": true,
"babel": {
"presets": [
"es2015-rollup"
]
},
"dependencies": {
"chart.js": "^1.0.2",
"crypto-js": "^3.1.6",
"mithril": "^0.2.2-rc.1",
"moment": "^2.11.1",
"pluralize": "^1.2.1"
},
"devDependencies": {
"babel-preset-es2015-rollup": "^1.1.1",
"rollup-plugin-babel": "^2.3.9",
"rollup-plugin-commonjs": "^2.2.0",
"rollup-plugin-npm": "^1.3.0",
"rollup-plugin-uglify": "^0.1.0"
}
}
rollup.config.js
import babel from 'rollup-plugin-babel';
import npm from 'rollup-plugin-npm';
import commonjs from 'rollup-plugin-commonjs';
import uglify from 'rollup-plugin-uglify';
export default {
entry: 'app/main.js',
format: 'cjs',
plugins: [
npm({
jsnext: true,
main: true,
}),
babel({
exclude: 'node_modules/**',
presets: [ 'es2015-rollup' ],
}),
commonjs(),
//uglify(),
],
dest: 'static/js/app.js',
}
main.js
import Application from './application'
import pluralize from 'pluralize'
var text = Application.run()
console.log(`Testing encryption: ${text}`)
console.log(`Testing pluralization: ${pluralize('person')}`)
application.js
import crypt from 'crypto-js'
var Application = {
run() {
var ciphertext = crypt.AES.encrypt('Testing encryption...', 'password')
var bytes = crypt.AES.decrypt(ciphertext.toString(), 'password')
return bytes.toString(crypt.enc.Utf8)
}
}
export default Application
Running the above will generate the errors.

Just speculating: Maybe is a bug of the rollup and/or crypto.
I have a similar error when trying to run a js function in Node Red, the js is ok when I run it locally but it throws TypeError: Cannot read property 'split' of undefined when runs remotely.
The only thing that my code have in common with yours is that both uses cryptography, specifically crypto-js 3.1.2 rollup "hmac-sha256.js" and the code is not imported but raw.
Even after deleting the only instance of 'split' yet I can't solve it (but keeps running locally)

Related

how to prevent multiple copies of React when developing library with Rollup?

I am developing tiny ui react library. I am using Rollup as a bundler. and i faced some strange issue:
react.development.js:1476 Uncaught Error: Invalid hook call. Hooks can only be called
inside of the body of a function component. This could happen for one of the
following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
Here is my Rollup config:
import babel from "rollup-plugin-babel";
import resolve from "#rollup/plugin-node-resolve";
import external from "rollup-plugin-peer-deps-external";
import { terser } from "rollup-plugin-terser";
import postcss from "rollup-plugin-postcss";
import typescript from "rollup-plugin-typescript2";
import peerDepsExternal from "rollup-plugin-peer-deps-external";
const packageJson = require("./package.json");
export default [
{
input: ["./src/index.ts"],
output: [
{
file: packageJson.main,
format: "cjs",
sourcemap: true,
},
{
file: packageJson.module,
format: "esm",
sourcemap: true,
},
],
globals: {
react: "React",
"react-dom": "ReactDOM",
},
external: ["react", "react-dom"],
plugins: [
peerDepsExternal({ includeDependencies: false }),
postcss({
plugins: [],
minimize: true,
}),
babel({
exclude: "node_modules/**",
presets: ["#babel/preset-react"],
}),
external(),
resolve(),
typescript({ useTsconfigDeclarationDir: true }),
terser(),
],
},
];
Component itself if very simple. Nothing special so i am skipping its code.
When i am publishing my lib to NPM - everything is working exactly as expected.
But when i am doing local instal with
npm i ../my-local-lib
I have this error in console:
react.development.js:1476 Uncaught Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
You might have mismatching versions of React and the renderer (such as React DOM)
You might be breaking the Rules of Hooks
You might have more than one copy of React in the same app
My expectation was that peerDepsExternal plugin will handle this case, but obviously i have messed up somewhere.

NextJS styled-components giving an error in bundle file

I am using styled-components for my React project. After I bundled my react application with rollupjs then I am trying to use this bundle with NextJS. It is getting error in NextJS:
ReferenceError: window is not defined
When I look line of error in the bundle file this error is happening inside of styled-components.
Here is my rollup.config.js in React App (not Nextjs):
import babel from "rollup-plugin-babel";
import commonjs from "#rollup/plugin-commonjs";
import external from "rollup-plugin-peer-deps-external";
import postcss from "rollup-plugin-postcss";
import resolve from "#rollup/plugin-node-resolve";
import image from "#rollup/plugin-image";
import visualizer from "rollup-plugin-visualizer";
import pkg from "./package.json";
// PostCSS plugins
import simplevars from "postcss-simple-vars";
import nested from "postcss-nested";
import cssnext from "postcss-cssnext";
import cssnano from "cssnano";
import cssvariables from "postcss-css-variables";
const extensions = [".js", ".jsx", ".ts", ".tsx"];
export default {
input: ["./src/index.js"],
output: [
{
file: pkg.main,
format: "cjs",
globals: { react: "React" },
},
{
file: pkg.module,
format: "esm",
},
],
plugins: [
external(["react", "uikit"]),
postcss({
plugins: [
simplevars(),
cssvariables(),
nested(),
cssnext({ warnForDuplicates: false }),
cssnano(),
],
extensions: [".css"],
}),
babel({
exclude: "node_modules/**",
extensions,
}),
// Allows node_modules resolution
resolve({
mainFields: ["module", "main", "jsnext:main", "browser"],
dedupe: ["react", "react-dom"], // Default: []
extensions,
}),
commonjs(),
image(),
visualizer(),
],
};
How can I solve this error in NextJS with bundle code?
Thanks
It means your window related code is executed on the Node.js side, not on the browser. Since Next.js is server-side rendering framework, you should make sure that you don't use browser thing (like window object) in the code that is executed on the server side.
Please reference this article.
UPDATE
Please check your .babelrc -
{
"presets": ["next/babel"],
"plugins": [["styled-components", { "ssr": true }]]
}

How can I get webpack to find angular modules?

I'm trying to setup a bare-bones application with Angular 1 + Typescript 2 and Webpack. The app works fine until I try to use an external module, ex: angular-ui-router.
It always complains that it can't find the dependency:
ERROR in ./src/app.ts Module not found: Error: Cannot resolve module 'angular-ui-router' in ./src/app.ts 3:26-54
Demo showing problem: https://github.com/jxc876/angular-ts
I suspect I'm not importing the routing dependency correctly, tried:
import uiRouter from 'angular-ui-router';
import * as uiRouter from 'angular-ui-router'
Tried with angular-route and also ui-router but neither works. Tried ts-loader and awesome-typescript-loader.
App
import * as angular from 'angular';
import uiRouter from 'angular-ui-router';
let myApp = angular.module('myApp', [uiRouter]);
myApp.config(function($stateProvider) {
let homeState = {
name: 'home',
url: '/home',
template: '<div>It works !!!</div>'
}
$stateProvider.state(homeState);
});
Config
package.json
{
"name": "ts-demo",
"scripts": {
"start": "webpack-dev-server --content-base ./src"
},
...
"devDependencies": {
"#types/angular": "^1.5.16",
"#types/angular-ui-router": "^1.1.34",
"awesome-typescript-loader": "^3.0.0-beta.3",
"typescript": "^2.0.9",
"webpack": "^1.13.3",
"webpack-dev-server": "^1.16.2"
},
"dependencies": {
"angular": "^1.5.8",
"angular-ui-router": "^0.3.1",
"enhanced-resolve": "^2.3.0"
}
}
webpack.config.js
module.exports = {
entry: './src/app',
output: {
filename: './dist/bundle.js'
},
resolve: {
extensions: ['.ts', '.tsx', '.js', '.jsx']
},
devtool: 'source-map',
module: {
loaders: [
{
test: /\.ts$/,
loader: 'awesome-typescript-loader'
}
]
}
};
tsconfig.json
{
"compilerOptions": {
"outDir": "./dist/",
"allowJs": true,
"target": "es5",
"module": "commonjs",
"moduleResolution": "node",
"strictNullChecks": true,
"listFiles": true
},
"include": [
"./src/**/*"
],
"exclude": [
"node_modules"
]
}
Finally figured this out.
First issue is that the typescript compiler removes import statements that are not used.
The compiler detects whether each module is used in the emitted JavaScript. If a module identifier is only ever used in type annotations and never as an expression then no require call is emitted for that module. This culling of unused references is a good performance optimization, and also allows for optional loading of those modules.
source: https://github.com/Microsoft/TypeScript/issues/4717
I assigned the imported value to a dummy array and it seems to fix this. Logging the value out to the console also works. (See my final note on why I couldn't simply pass it into the dependency array).
EDIT: Better solution is to use import "module"; syntax since that is always emitted based on the github above, ex: import 'angular-ui-router';
Second, my webpack file was missing an empty string in the resolve array:
resolve { extensions: ['', '.ts', '.js'] }
Without this it couldn't pull in the file for ui router.
A few things I noticed while working on this: webpack --display-error-details is super useful. For some reason it was looking for double .js.js extensions inside node_modules/angular-ui-router/release:
resolve file
/Users/mich2264/projects/angular-ts/node_modules/angular-ui-router/release/angular-ui-router.js.ts doesn't exist
/Users/mich2264/projects/angular-ts/node_modules/angular-ui-router/release/angular-ui-router.js.js doesn't exist
--traceResolution is equally useful for typescript.
EDIT: Appears to be a awesome-typescript-loader loader bug:
https://github.com/s-panferov/awesome-typescript-loader/pull/264
Finally, I'm not sure why but when I import the default value from angular-ui-router and I log it or set a breakpoint it shows up correctly as ui.router, but if I attempt to pass it into the dependency array it becomes undefined.
#types/angular-ui-router defines the following export inside their type file : export default "ui.router";
This one should do the job:
import * as angular from 'angular';
import * as uiRouter from 'angular-ui-router';
let myApp = angular.module('myApp', ['ui.router']);
Notice, that import is just importing router code and in application module you need to inject 'ui.router' string.
I suppose that since I'm using UI-Router for AngularJS (1.x), I had to use...
import '#uirouter/angularjs'
...instead of...
import 'angular-ui-router'

React Webpack Production errors

I'm trying to setup a webpack (1.13.3) config for a React (15.3.2) app, and I want the production version of React in my production build. I'm on Windows.
I'm using this (which is everywhere online when you search):
new webpack.ProvidePlugin({
'process.env': {
'NODE_ENV': JSON.stringify('production')
}
})
However, as soon as I add this and run webpack (CLI) I get slapped round the face with many many errors.
I get a whole bunch of these warnings:
WARNING in ./~/fbjs/lib/partitionObject.js.flow
Module parse failed: C:\node\sandbox\react-webpack\node_modules\fbjs\lib[ SOME FILE NAME HERE].flow Unexpected token (18:24)
You may need an appropriate loader to handle this file type.
...and a bunch of these errors:
ERROR in ./~/react/lib/NativeMethodsMixin.js
Module not found: Error: Cannot resolve module 'react-native/lib/TextInputState' in C:\node\sandbox\react-webpack\node_modules\react\lib
# ./~/react/lib/NativeMethodsMixin.js 17:21-63
I'm not using React Native, I wouldn't know how.
I'm also using webpack.optimize.UglifyJsPlugin in my webpack.config.production.js file.
When I remove the webpack.ProvidePlugin bit the build works, but includes the development version of React and I get warnings in the console:
Warning: It looks like you're using a minified copy of the development build of React. When deploying React apps to production, make sure to use the production build which skips development warnings and is faster.
What are these webpack errors all about..? How do I get a production build of React which is also minified..?
UPDATE
Full webpack config requested. I've setup a test app for this, with minimum config and the warnings and errors are still showing:
webpack.config.js
module.exports = process.env.NODE_ENV === 'production' ? require('./webpack.config.production.js') : require('./webpack.config.development.js')
webpack.config.base.js
module.exports = {
entry: {
'bundle': './client/index.js'
},
output: {
path: './public',
filename: 'js/[name].js'
},
module: {
loaders: [
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
loader: 'babel-loader',
query: { presets: ['es2015', 'react'] }
}
]
}
}
webpack.config.development.js
var config = require('./webpack.config.base')
module.exports = config
webpack.config.production.js
var webpack = require('webpack')
var config = require('./webpack.config.base')
config.plugins = [
new webpack.ProvidePlugin({
'process.env': {
'NODE_ENV': JSON.stringify('production')
}
}),
new webpack.optimize.UglifyJsPlugin({
include: /\.js$/,
compress: { warnings: false }
})
]
module.exports = config
The test app I'm using only has the following installed:
"dependencies": {
"express": "^4.14.0",
"react": "^15.3.2",
"react-dom": "^15.3.2"
},
"devDependencies": {
"babel": "^6.5.2",
"babel-core": "^6.18.2",
"babel-loader": "^6.2.7",
"babel-preset-es2015": "^6.18.0",
"babel-preset-react": "^6.16.0",
"webpack": "^1.13.3"
}
/client/index.js
import React from 'react'
import ReactDOM from 'react-dom'
import Hello from '../components/Hello'
ReactDOM.render(<Hello />, document.getElementById('page'))
/components/Hello.js
import React from 'react'
const Hello = props => <p>Hello world...</p>
export default Hello
Asked again in a separate question, but with the full error list, and from a React Native view, because the errors contain references to React Native, even though I'm not trying to use it:
Webpack in production: Why React Native errors?
Answered here: Webpack in production: Why React Native errors? by Aruna Herath.
I should be using DefinePlugin not ProvidePlugin.

Karma can't load webpack

I'm getting this error;
16 07 2015 13:03:52.741:WARN [preprocess]: Can not load "webpack"!
Error: Can not resolve circular dependency! (Resolving: preprocessor:webpack -> webpackPlugin -> preprocessor:webpack)
My karma.conf looks like;
var webpack = require('webpack');
module.exports = function (config) {
config.set({
browsers: [ 'Chrome' ], //run in Chrome
singleRun: true, //just run once by default
frameworks: [ 'mocha' ], //use the mocha test framework
files: [
'tests.webpack.js' //just load this file
],
preprocessors: {
'tests.webpack.js': [ 'webpack', 'sourcemap' ] //preprocess with webpack and our sourcemap loader
},
reporters: [ 'dots' ], //report results in this format
webpack: { //kind of a copy of your webpack config
devtool: 'inline-source-map', //just do inline source maps instead of the default
module: {
loaders: [
{ test: /\.js$/, loader: 'babel-loader' }
]
}
},
webpackServer: {
noInfo: true //please don't spam the console when running in karma!
}
});
};
and tests.webpack.js
var context = require.context('./src', true, /-test\.js$/); //make sure you have your directory and regex test set correctly!
context.keys().forEach(context);
I do have karma and karma-webpack installed.
Any ideas ?
I had a similar error but the post referenced in the accepted solution did not work for me. If you're looking for alternatives, read below!
I was seeing the following error message:
WARN [preprocess]: Can not load "webpack"!
TypeError: Object [object Object] has no method 'refreshFiles'
at Plugin.notifyKarmaAboutChanges (/Users/abhandaru/workspace/source/macaw-campaigns/node_modules/karma-webpack/index.js:108:15)
at Plugin.<anonymous> (/Users/abhandaru/workspace/source/macaw-campaigns/node_modules/karma-webpack/index.js:72:9)
at Tapable.applyPlugins (/Users/abhandaru/workspace/source/macaw-campaigns/node_modules/webpack/node_modules/tapable/lib/Tapable.js:26:37)
I found this solution on a Github issue:
https://github.com/webpack/karma-webpack/issues/65
Here is are the updated lines in my package.json:
"karma": "^0.13.3",
"karma-chrome-launcher": "^0.2.0",
"karma-jasmine": "^0.3.6",
"karma-webpack": "^1.7.0",
Hope this helps.
Something has changed in the latest versions of karma-* projects. I have got the same issue as I installed everything latest. Now I tried exactly the versions here and it worked out.
You should upgrade "karma" and "karma-webpack" packages. Had similar exception, upgrading to next versions solved this:
"karma": "0.13.18",
"karma-webpack": "1.7.0"

Categories