12

I'm building an isomorphic React/React-Router/Redux/Webpack application and I'm attempting to implement server side rendering.

My directory looks like:

/client
    /actions
    /components
    /containers
/server
    /server.js

In my webpack config, I have aliases set up for all the folders inside client:

var path_base = path.resolve(__dirname, '..');
const resolve = path.resolve;
const base = function() {
  var args = [path_base];
  args.push.apply(args, arguments);
  return resolve.apply(resolve,args);
};
const resolve_alias = base.bind(null, 'src/client');
const aliases = [
  'actions',
  'components',
  'constants',
  'containers',
  'middleware',
  'reducers',
  'routes',
  'store',
  'styles',
  'utils',
  'validation'
];

so that inside the code that gets bundled by webpack, I can do:

import { Widget } from 'components'; 

and that import gets resolved by webpack.

Now in my server code, in order to do the rendering, I have to import some of my client files, like routes/index.js. The problem I'm running into when I import my routes file, it's using a webpack alias to another file, say components or containers so naturally, the node js require system can't resolve it.

How do I fix something like that? I looked at this question and it talks about essentially setting up the same aliases that exist in webpack with mock-require. But then the issue becomes that my routes file imports all my components which then all import things like stylesheets, images, etc. Should I then be using something like webpack-isomorphic-tools?

The guides I've been looking at (this for example) are all great at showing how server side rendering is accomplished but none of them really talk about how to resolve all the requires and whatnot.

Community
  • 1
  • 1
barndog
  • 6,975
  • 8
  • 53
  • 105
  • It sounds like there are several questions here: (a) how do I use the aliases when running server-side, and (b) how do I handle included resources like stylesheets on the server. One solution is to run your server code through webpack too. You can use `target: node` in your config and it will optimize it for node during the build (i.e. it won't bundle node includes). I do this sometimes for code that uses Babel. Short of doing a build, definitely don't use aliases. Any solution will be hacky at best. – Josh David Miller Jan 08 '16 at 23:22
  • Why shouldn't I use aliases? – barndog Jan 09 '16 at 01:05
  • Aliases are fine when you're doing a *build* with webpack. Your problem is because you are using aliases in a webpack build and trying to get the same code to work *outside* a webpack build. My point was that to use the aliases, you need to build your server code too (which will make the aliases work just fine). Without the build, the only way to get aliases to work is to hack it together, which is where your problem is. Hacks are bad, so use the aliases and build your server code too, or just abandon the aliases. – Josh David Miller Jan 09 '16 at 01:20
  • Then using something like webpack-isomorphic-tools shouldn't be a problem then because that supports aliases, for both server and client code. – barndog Jan 09 '16 at 01:46
  • I can't speak to that tool as I've never needed to use it. It seems to me like the very kind of hack I was recommending you avoid. But after this back-and-forth and the one on the answer below, I am honestly not sure what a valid answer to your question would be. Is there one? What are you looking for from the community here on SO? – Josh David Miller Jan 09 '16 at 05:51
  • I'm the author of webpack-isomorphic-tools. If you have questions, ask. – catamphetamine Jan 10 '16 at 14:23
  • @asdfasdfads I ended up using it and it works great. I just import my aliases from my config into my isomorphic config and everything works great. – barndog Jan 11 '16 at 18:32
  • Also, this could be useful: https://github.com/halt-hammerzeit/universal-webpack – Vlady Veselinov Oct 05 '16 at 00:17
  • @startupthekid I'm struggling to set up isomorphic tools, are there any good examples for this resolving thing out there? – Vlady Veselinov Oct 06 '16 at 01:36
  • @VladyVeselinov definitely use universal-webpack. I haven't been able to find good examples on it apart from on the github README which generally serves pretty well. If you want, I can post a gist of the config files I use – barndog Oct 06 '16 at 03:27
  • @startupthekid That would be awesome, I'm just getting into it and my pigeon brain just can't comprehend what's going on... – Vlady Veselinov Oct 06 '16 at 03:41
  • 1
    https://gist.github.com/startupthekid/3223a866616b6dc59e4d5d4fc03275a7. I included my aliases file, all the configs, and then my scripts from my package.json. There's a ton of files, four for the server and client each (base config, dev config, production config, production entry file, and development entry file) and then a base configuration file as well as the universal webpack config file. I don't have all of them in the gist (I haven't set up production configs yet) but that should be a good start for you – barndog Oct 06 '16 at 03:51
  • Thanks @startupthekid this got me far, I'm having some weird resolve issues despite using it though, would you mind checking this out https://github.com/halt-hammerzeit/webpack-react-redux-isomorphic-render-example/issues/10 – Vlady Veselinov Oct 06 '16 at 23:45
  • I'd take a look at the gist, I have a `aliases` file that works for me. I resolved them using `path` and I pass the fully resolved paths into my webpack config. – barndog Oct 07 '16 at 08:15
  • All good, thanks for the help! – Vlady Veselinov Oct 07 '16 at 17:28

4 Answers4

6

After battling with this issue for 2 days I settled on babel-plugin-webpack-alias. What you need to do to resolve paths with that is:

  1. $ npm install --save-dev babel-plugin-webpack-alias
  2. Add the plugin to your .babelrc
  3. Add the aliases to your webpack.config (make sure you use path.join())
  4. Refer to this post if you have problems loading styles

The other option I tried was universal-webpack but I found it to be a bit verbose. If you want to see roughly how the whole server-side loading works, you can check out this video.

Community
  • 1
  • 1
Vlady Veselinov
  • 4,678
  • 5
  • 23
  • 49
  • `babel-plugin-webpack-alias` works, but seems like it breaks Jest. Isolating this plugin to Babel's `development` environment (via the `env` config key) fixed that for me – FeifanZ Apr 27 '18 at 01:21
1

If you really want them, run your server side code through babel and use this plugin: https://www.npmjs.com/package/babel-plugin-module-alias which will let you do the same thing as webpack.

Edit: This one works a lot better: https://github.com/jagrem/babel-resolve-relative-module it allows multiple paths

zackify
  • 5,314
  • 2
  • 22
  • 28
  • What's the reasoning behind not using them? – barndog Jan 09 '16 at 01:05
  • 1
    It just seems to cause problems plus you have to rely on using at the very least a plugin on the server, and probably running your whole code base through Babel. Which I guess is fine but if the only reason you pull in Babel is for aliases, seems like a lot of work – zackify Jan 09 '16 at 04:01
  • THANK YOU for linking to that Babel plugin! I hadn't thought to look on the Babel side of things for aliasing. This helped me a lot! – Kevin Feb 09 '16 at 23:30
0

Try to use NODE_PATH. Node will always look for a module in this path during require calls. It allows to short cut your relative paths as you want.

// turn this
import {Widget} from '../../components';

// into this
import {Widget} from 'components';

See Node.js docs for more information.

P.S. this thing is very sensitive, so use it carefully. Now your code tightly depends from the environment and may break somewhere.

just-boris
  • 9,468
  • 5
  • 48
  • 84
0

If you use webpack-isomorphic-tools then it'll take your webpack config into account for your server side which will make all your aliases work.

https://www.npmjs.com/package/webpack-isomorphic-tools

Andrew Rasmussen
  • 14,912
  • 10
  • 45
  • 81