Closed omerts closed 8 years ago
Please see this https://github.com/kirjs/react-highcharts/issues/12#issuecomment-122085876. Although its for Highcharts the same logic applies.
Related issue: chartjs/Chart.js#1328
Below is an another fix for those who want to develop an isomorphic react app.
In my package.json
:
"scripts": {
// ...
"postinstall": "npm i find-up prepend-file && node scripts/postinstall.js",
// ...
},
"dependencies": {
"chart.js": "^2.1.6",
// ...
"react-chartjs": "github:jhudson8/react-chartjs#chartjs-v2",
// ...
},
"devDependencies": {
// ...
"prepend-file": "^1.3.0",
// ...
}
In my webpack config
(used to generate the client side code):
plugins: [
// ...
new webpack.DefinePlugin({
'process.env.BROWSER': JSON.stringify(true)
}),
// ...
]
And the postinstall.js
script:
#!/usr/bin/env node
var path = require('path');
var prepend = require('prepend-file');
var findUp = require('find-up')
var FIXED_FILE = ['chart.js', 'src', 'core', 'core.helpers.js'];
var FIXED_CODE = '// < HACK >\n'
+'if (!process.env.BROWSER) {\n'
+' global.window = {};\n'
+'}\n// </ HACK >\n\n';
function hackChartJs() {
findUp('node_modules')
.then(nodeModules => prepend(
path.resolve.apply(path, [nodeModules].concat(FIXED_FILE)),
FIXED_CODE,
console.log
));
}
hackChartJs();
So when I install my app, the postinstall.js
script will prepend the file node_modules/chart.js/src/core/core.helpers.js
with the codefix below:
// < HACK >
if (!process.env.BROWSER) {
global.window = {};
}
// </ HACK >
That is ugly but it works.
Update 11 july 2016:
Another way to solve this would be to use code splitting. https://webpack.github.io/docs/code-splitting.html#defining-a-split-point
If you dynamically require Chart.js
inside of ComponentDidMount
and then initialize the chart in the callback, you can avoid a lot of nasty workarounds.
I added the following to core.helpers.js:
if (typeof window === 'undefined') {
global.window = {}
}
Works a treat. Can use the same method as @enten uses above to make sure this is always prepending to core.helpers.js on install.
@enten Good fix - it works for those of us that aren't using webpack, and it worked for my Meteor based solution.
However - with your code every time we run an 'npm install' it's going to write multiple copies of the javascript code we want to prepend.
So I came up with an add-on to your solution and mixed up @mtford90 's code. This takes a regular expression and searches for the // < HACK > till the end of the // < /HACK > and deletes it if it exists, before prepending the new one. After I wrote this, I realized the most optimized approach would be to actually search to see if it exists, then prepend the code otherwise don't.. but here goes :) !
Packages installed to dev-dependencies for this code: path, prepend-file, find-up and replace-in-file.
`var path = require('path'); var prepend = require('prepend-file'); var findUp = require('find-up'); var replace = require('replace-in-file');
var FIXED_FILE = ['chart.js', 'src', 'core', 'core.helpers.js'];
var FIXED_CODE = '// < HACK >\n'
+'if (typeof window === \'undefined\') {\n'
+' global.window = {};\n'
+'}\n// </ HACK >\n\n';
function hackChartJs() {
findUp('node_modules')
.then(nodeModules => {
var completeFilePath = path.resolve.apply(path, [nodeModules].concat(FIXED_FILE))
var replace_options = {
files: completeFilePath,
from: /\/\/ < HACK >[\s\S]*?\/\/ <\/ HACK >[\s]*/g,
to: '',
};
try {
var changes = replace.sync(replace_options);
console.log('Modified files:', changes.join(', '));
}
catch (error) {
console.error('Error occurred:', error);
}
prepend(
completeFilePath,
FIXED_CODE,
console.log
);
});
}
hackChartJs();`
Works like a charm and now my meteor + react-router-ssr (Server Side Rendering for React) project works beautifully!
Hello,
Trying to use this library with server-side rendering, but I am getting a "window is not defined error", since Chart.js is referencing the browser's window object, even if it is only imported, before any usage.