Skip to content
This repository has been archived by the owner on Sep 2, 2021. It is now read-only.

Server side rendering #11

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "imager.jsx",
"version": "1.1.3",
"version": "1.2.0",
"description": "A React component for responsive images in desktop and mobile browsers. Featuring Imager.js.",
"main": "./src/imager.jsx",
"repository": {
Expand Down Expand Up @@ -36,12 +36,12 @@
"author": "Thomas Parisot (https://oncletom.io)",
"license": "MIT",
"dependencies": {
"imager.js": "^0.4.0",
"react": "^0.12.1"
"imager.js": "^0.5.0",
"react": "^0.13.3"
},
"devDependencies": {
"browserify": "^6.3.2",
"reactify": "^0.17.1",
"watchify": "^2.1.1"
"browserify": "^10.2.3",
"reactify": "^1.1.1",
"watchify": "^3.2.1"
}
}
65 changes: 55 additions & 10 deletions src/imager.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
'use strict';

var isBrowser = (typeof window !== 'undefined');

var React = require('react');
var Imager = require('imager.js');

var Imager = isBrowser ? require('imager.js') : null;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would rather use the browser field of package.json to shim imager (or not).

Server-side, the onResize would be always falsy, and the verification would be related to imgr.onResize rather than onResize directly.

The code remains equal both for the browser and the server, and the behaviour is only driven by what imager.js is supposed to be.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right! Shiming the Imager directly is definitly the cleaner solution.


/**
* Imager.jsx Component Factory
Expand All @@ -20,9 +23,9 @@ module.exports = function (config) {

// Where the magic happens.
// A 'blind' Imager instance shared by all the rendered components.
var imgr = new Imager([], imagerConfig);
var imgr = isBrowser ? new Imager([], imagerConfig) : null;

if (onResize) {
if (isBrowser && onResize) {
Imager.addEvent(window, 'resize', Imager.debounce(function(){
Imager.applyEach(imagesCache, function(component){
component.refreshImageWidth();
Expand All @@ -34,16 +37,16 @@ module.exports = function (config) {
propTypes: {
// mandatory props
src: React.PropTypes.string,
'background-src': React.PropTypes.string,
// optional props
lowSrc: React.PropTypes.string,
alt: React.PropTypes.string,
className: React.PropTypes.string
},

componentDidMount: function () {
this.refreshImageWidth();

if (onResize) {
if (isBrowser && onResize) {
imagesCache.push(this);
}
},
Expand All @@ -54,7 +57,7 @@ module.exports = function (config) {
componentWillUnmount: function () {
var self = this;

if (onResize) {
if (isBrowser && onResize) {
imagesCache = Imager.applyEach(imagesCache, function(component){
return component === self ? null : component;
}).filter(function(c){ return c; });
Expand All @@ -67,9 +70,9 @@ module.exports = function (config) {

getDefaultProps: function () {
return {
className: imgr.className,
src: imgr.gif.src,
alt: imgr.gif.src
className: imgr ? imgr.className : 'image-replace', // add imagers className to server side rendering. It's kind of dirty but fixes Reacts invalid checksum warning for now.
src: imgr ? imgr.gif.src : '',
alt: imgr ? imgr.gif.src : '' // <-- why are you using the src as alt attribute here?
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably a typo.

};
},

Expand All @@ -79,9 +82,51 @@ module.exports = function (config) {
}
},

getLowSrc: function () {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This ideally would have been a different PR but let's not make it more complicated :-)

var lowSrc = this.props.src;

// use the defined low src property
if (this.props.lowSrc) {
lowSrc = this.props.lowSrc;
}
// use the smallest width and replace it in the default src property
else {
var smallestWidth = -1;
var replacement = '';

if (config.availableWidths) {
if (config.availableWidths.constructor === Array && config.availableWidths.length) {
for (var i = 0, l = config.availableWidths.length; i < l; i++) {
var width = config.availableWidths[i];
if (smallestWidth === -1 || smallestWidth > width) {
smallestWidth = width;
replacement = width;
}
}
}
else if (config.availableWidths !== null && typeof config.availableWidths === 'object') {
var keys = Object.keys(config.availableWidths);

for (var i = 0, l = keys.length; i < l; i++) {
var width = parseInt(keys[i], 10);

if (smallestWidth === -1 || smallestWidth > width) {
smallestWidth = width;
replacement = config.availableWidths[width];
}
}
}
}

lowSrc = this.props.src.replace('{width}', replacement);
}

return lowSrc;
},

getImageSrc: function () {
if (!this.state.width) {
return imgr.gif.src;
return this.getLowSrc();
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is a bit ambiguous why the lowSrc is loaded if the width is not available. Any reason why?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The width is currently calculated via the imager module at and updated afterwards. Using lowScr (the smallest version) whenever we don't have any information about the width tries to follow the mobile first appoach.
Alternatively we could shim the imgr.gif.scr property and use a transparent gif, but we have to render the same DOM on the client and the server to get the full advantage of server-side rendering and serving the page without images from the server isn't a good idea…

}

return imgr.changeImageSrcToUseNewImageDimensions(this.props.src, this.state.width).replace('{height}', this.state.height);
Expand Down