Webpack require ensure large modules - node.js

I'm using the d3 library. Its pretty big, so I only want to download the chunk on demand. I can create the split point with require.ensure, but I'm lost as to how you actually get the library into the scope of the module. This is as close as I can get, the chunk is downloaded, but d3 is always undefined. Any help would be greatly appreciated.
var React = require('react');
var d3;
require.ensure([], function(require){
d3 = require('d3');
});
var Chart = React.createClass({
render: function() {
var props = this.props;
var width = props.width;
//d3 is undefined here
var xScale = d3.scale.linear().domain([
0, 111
]).range([
0, width
]);
return (
<g>
</g>
);
}
});
module.exports = Chart;

From my understanding the mechanism goes like this:
require.ensure(["<file-path or module name>"], function(moduleExportsValue) {
var myModule = require("<file-path or module name>");
});
for your specific example:
require.ensure(["d3"], function() {
var d3 = require("d3");
// do something with d3
});
Edit: It's very helpful for stuff that is not immediately visible in the app. Such as dialogs, modals, overlays.
onButtonClick: function(event) {
this.showLoader();
var self = this;
require.ensure("path/to/dialog", function() {
self.hideLoader();
var dialog = require("path/to/dialog");
dialog.open();
});
},

Related

How to convert jquery function to nodejs module

I build a web page with nodejs & koa & ejs, and in webpage.ejs, there's a function like following
<a id="createACode"></a>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script>
var code;
function createCode(){
code = "";
var codeLength = 6;
var checkCode = document.getElementById("createACode");
var random = new Array(2,3,4,5,6,7,8,9,'A','B','C','D','E','F','G','H','J','K','M','N','P','Q','R',
'S','T','U','V','W','X','Y','Z');
for(var i = 0; i < codeLength; i++) {
var index = Math.floor(Math.random()*30);
code += random[index];
}
createACode.text = code;
}
$(document).ready(function(){
$("#createACode").click(function(){
createCode();
});
});
</script>
When I click the a link with ID createACode, its text will be changed, and app.js like this
.get('/webpage', async ( ctx )=>{
await ctx.render('webpage', {
});
})
And if I want to convert this function createCode to module in nodejs, and how to convert, and use it? Many thanks.

D3 Geo Projection plugin cannot find module 'fs'

I'm trying to display a D3 geo projection in a React component.
When viewing any page, this error happens inside the D3 Geo projection module:
Object doesn't support property or method 'readFileSync'
It is thrown at this line in the module's index.js:
module.exports = new Function("d3",
fs.readFileSync(path.join(__dirname, "d3.geo.projection.js"), "utf-8"));
Here are the modules added to the package.json as dependencies:
"d3": "^3.5.16",
"d3-geo-projection": "^0.2.16",
"topojson": "^1.6.25"
The following is the code for my GeoMap React component using D3 geo projection plugin:
var React = require('react');
var ReactDOM = require('react-dom');
var d3 = require("d3");
require("d3-geo-projection")(d3);
var d3GeoMap = {};
d3GeoMap.create = function(el, props, state) {
var svg = d3.select(el).append("svg")
.attr("class", "geoChart")
.attr("width", props.width)
.attr("height", props.height);
this.update(el, state);
};
d3GeoMap.update = function(el, state) {
d3.select(el).select("svg").append("rect")
.data(state.data)
.enter()
.attr("class", "map")
.attr("d", d3.geo.path().projection(d3.geo.mercator()));
};
var GeoMap = React.createClass({
propTypes: {
data: React.PropTypes.object
},
componentDidMount: function() {
var el = this.refs.geoRoot;
d3GeoMap.create(el,
{
width: 900,
height: 900
},
{
data: this.props.data
});
},
render: function() {
return (<div ref="geoRoot"></div>);
}
});
module.exports = GeoMap;
NOTE: This error happens when hitting any page, even ones that do not use my GeoMap component.
Does anyone have insight on why the D3 Geo Projection plugin cannot find the 'fs' module?
require("d3-geo-projection") when bundled assumes that fs.readFileSync is replaced with the actual code which for example in browserify is done with the brfs transform
However the index.js file is just doing the following
module.exports = function (d3) {
// all the code of ./d3.geo.projection.js is included here
}
Therefore if you're not using a bundler with this transform use this instead
var d3 = require("d3");
// assumes that d3 is already defined here
require("d3-geo-projection/d3.geo.projection")

How can I pipe external html content in jade?

I'm trying to get some html from a page online and place inside my jade template so I can style without copying and pasting every time a need it.
var request = require("request");
var cheerio = require("cheerio");
var loadContent = function() {
request({
uri: "http://www.mywebsite.com.br/test"
}, function(error, response, body) {
var $ = cheerio.load(body);
var result;
$('.content').each(function(){
result={"content":$(this).html()};
});
placeContent(result);
return true;
});
};
var placeContent = function(content) {
return content;
};
module.exports = loadContent;
Inside my gulpfile.js, besides the right requirements, I have:
gulp.task('jadeBuild', function() {
var options = {
pretty: true
};
return gulp.src(src+'/*.jade')
.pipe(data(function(){
return loadContent();
}))
.pipe(jade(options))
.pipe(gulp.dest(build))
.pipe(connect.reload());
});
And my jade file:
.mycontent
#{content}
What am I missing?
Try changing #{content} to !{content} in your jade file. This will tell jade not to escape any of the characters(which can be dangerous depending on where the input is coming from!).
See http://jade-lang.com/reference/interpolation/
Also, when you loop over each .content you are overwriting result every time. You need to append to result if you want to aggregate all the content together. Something like:
var result = {content: ''};
$('.content').each(function(){
result.content += $(this).html();
});

has no method of emit in node.js

I made a simple example like below, and I got a error saying 'has no method of 'emit' ', what is the issue ?
var events = require('events');
var EventEmitter = require('events').EventEmitter;
var util = require('util');
var Door = function (options) {
events.EventEmitter.call(this);
}
util.inherits(Door, EventEmitter);
Door.prototype = {
open:function(){
this.emit('open');
}
}
var frontDoor = new Door('brown');
frontDoor.on('open', function() {
console.log('ring ring ring');
});
frontDoor.open();
You are replacing the prototype of Door with a new object, which overwrites (/removes) the EventEmitter prototype methods as well:
Door.prototype = {
open:function(){
this.emit('open');
}
}
Instead, just add a single entry to the existing prototype:
Door.prototype.open = function() {
this.emit('open');
};

Socket.io began to support binary stream from 1.0, is there a complete example especially for image

I'm a beginner on node.js and socket.io. Socket.io began to support binary stream from 1.0, is there a complete example especially for image push to client and show in canvas? thanks
The solution is a bit complicated but should work in Chrome, Firefox, and IE10+ (not sure about Opera and Safari):
Somewhere on the server-side:
io.on('connection', function(socket){
fs.readFile('/path/to/image.png', function(err, buffer){
socket.emit('image', { buffer: buffer });
});
});
And here is how you handle it on a client:
socket.on('image', function(data) {
var uint8Arr = new Uint8Array(data.buffer);
var binary = '';
for (var i = 0; i < uint8Arr.length; i++) {
binary += String.fromCharCode(uint8Arr[i]);
}
var base64String = window.btoa(binary);
var img = new Image();
img.onload = function() {
var canvas = document.getElementById('yourCanvasId');
var ctx = canvas.getContext('2d');
var x = 0, y = 0;
ctx.drawImage(this, x, y);
}
img.src = 'data:image/png;base64,' + base64String;
});
Just replace yourCanvasId with your canvas id :)
thanks, #sovente, in this 1.0 introduction http://socket.io/blog/introducing-socket-io-1-0/ , this is code snippet on binary support.
var fs = require('fs');
var io = require('socket.io')(3000);
io.on('connection', function(socket){
fs.readFile('image.png', function(err, buf){
// it's possible to embed binary data
// within arbitrarily-complex objects
socket.emit('image', { image: true, buffer: buf });
});
});
i want to know how to handle the buffer on client side, codes are like:
socket.on("image", function(image, buffer) {
if(image)
{
console.log(" image: ");
**// code to handle buffer like drawing with canvas**
}
});
Starting from socket.io 1.0 it is possible to send binary data.
http://socket.io/blog/introducing-socket-io-1-0/
How ever the way of sending and receiving binary data is not clear in the official documentation. The only documentation is:
var socket = new WebSocket('ws://localhost');
socket.binaryType = 'arraybuffer';
socket.send(new ArrayBuffer);
I suggest you to take a look at this answer, where you can find code implementation for server and client (javascript, java):
https://stackoverflow.com/questions/34056705/how-to-send-binary-data-with-socket-io/
The good part is that it also works on Android!
Cheers

Resources