Razzle: How to load images and other static assets?

Created on 25 Apr 2016  ·  17Comments  ·  Source: jaredpalmer/razzle

Hello,

What is the best way to load images and other assets that will work for both client & server?
I could add url-loader and file-loader to webpack config but it will not work on the server.

Are there other options?

Thanks,
Ran.

bug question

Most helpful comment

@justingreenberg babel-register can't handle the image file types, a workaround is to modify server:

require('babel-register');
if (process.env.NODE_ENV == 'development') {
  require.extensions['.png'] = function () {};
  require.extensions['.jpg'] = function () {};
  require.extensions['.jpeg'] = function () {};
  require.extensions['.woff'] = function () {};
  require.extensions['.woff2'] = function () {};
  require.extensions['.ico'] = function () {};
  require.extensions['.svg'] = function () {};
}
require('./server');

All 17 comments

for example and for fonts, you could add the following :

,
{
  test: /\.(woff)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
  loader: "url?limit=100000&mimetype=application/font-woff"
}

server does not understand image extension, you need use require hook for ssr
https://github.com/bahmutov/node-hook

also you can add in this file server

require('babel-register')
if (development variable) require.extensions['.png'] = function () {};
require('./server')

I've used https://github.com/tcoopman/image-webpack-loader to deal with the images. I think it is based on file-loader, but allows you to optimise images.

closing this

@jaredpalmer hey man, thanks for the awesome kit :) i'm sorry to drudge this back up, but may i ask how you are handling SSR images/statics like fonts in your projects? for example, how are you approaching:

// logo-component.js
import LogoImage from './logo.png' // colocated image in component folder

export default ({ linkUrl }) =>
  <a href={linkUrl}>
    <img src={LogoImage} alt="Logo" /> 
  </a>

i've been using webpack-isomorphic-tools to handle above cases, which works but the ergonomics and setup feels very brittle and hacky... i'm about to start another project, it would be really great to hear your thoughts and approach—it feels like assets.json could be used for statics as well

thanks again jared, any direction, boilerplate or webpack config you could provide would be greatly appreciated, and i'd be happy to submit a PR if it's something you want to add to starter

i suspect i'm probably overlooking a super simple solution.... thanks again!! :)

All you need to do install url-loader via npm and then add the following to each webpack.config:

      ....
      {
        test: /\.(gif|jpe?g|png|ico)$/,
        loader: 'url-loader?limit=10000'
      },
      {
        test: /\.(otf|eot|svg|ttf|woff|woff2).*$/,
        loader: 'url-loader?limit=10000'
      }
      ...

You can then just require them in exactly as you described above. BTW the limit parameter just tells url-loader at what threshold it should actually generate an image vs. creating a data-uri.

EDIT:

Also remove new webpack.IgnorePlugin(/\.(css|less|scss|svg|png|jpe?g|png)$/), from webpack server config.

@jaredpalmer thanks for the response :) that's exactly the issue i was running into... like i said, i was able to resolve using https://www.npmjs.com/package/webpack-isomorphic-tools but it really feels very clunky...

@rowellx68 you mentioned using image-webpack-loader—could you maybe elaborate?

@b2whats would you mind providing some additional context or example for your node-hook solution? is there a way to integrate with assets plugin, so we can use a single manifest?

@justingreenberg babel-register can't handle the image file types, a workaround is to modify server:

require('babel-register');
if (process.env.NODE_ENV == 'development') {
  require.extensions['.png'] = function () {};
  require.extensions['.jpg'] = function () {};
  require.extensions['.jpeg'] = function () {};
  require.extensions['.woff'] = function () {};
  require.extensions['.woff2'] = function () {};
  require.extensions['.ico'] = function () {};
  require.extensions['.svg'] = function () {};
}
require('./server');

@justingreenberg image-webpack-loader will just optimize your images... you would use it in tandem with file-loader:

...
      {
        test: /\.(png|jpg|jpeg|gif)(\?.*)?$/,
        loaders: [
          'file',
          'image-webpack?' + JSON.stringify({
            bypassOnDebug:true,
            progressive: true,
            optimizationLevel: 7,
            interlaced: true,
            pngquant: {
              quality: "65-90",
              speed: 4
            },
            svgo: {
              removeUnknownsAndDefaults: false,
              cleanupIDs: false
            }
          })
        ]
      },

I would still use url-loader for fonts and svg's with this.

@rowellx68 @b2whats should we create a PR for this with url-loader? What are downsides of the require.extension in dev ? It's ugly, but cleaner than bundling the server just for dev IMHO. 🤔

@jaredpalmer re: patching require workaround, this is an interesting approach... so manually registering extensions with require just allows the module to hit url-loader, makes sense!

re: image-webpack, that was my understanding (really an optimization) but i thought maybe there was something i was missing for node usage since @rowellx68 said he was using it for images

thanks again!

@jaredpalmer require.extensions seems to have been deprecated?

@justingreenberg re: image-webpack-loader. It is indeed primarily for optimising images. However, the resulting images were not added into assest.json.

@rowellx68
we need slice dev and prod mode. webpack config may be different. In dev mode we need from the server get normal url of the image. In prod mode we can use any optimizations

I have modified build scripts. There is now a pbulic folder for you robots.txt, favicon etc. It's not the "perfect solution" but it works. Bundles js -> public/assets (which is not checked into git).

Will explore @justingreenberg 's requireHooks solution as that would allow for inlining and cache busting.

hey all, let me know if this is out of scope, but the static assets discussion seemed somewhat relevant.

I'm someone who is fairly new to the webpack world (read: no clue how to use it yet) and I'm trying to use this project to build a web app using a client's style guide. rather than reapplying CSS styles over and over I'm trying to load a CSS file that contains the client's style guide. is there a quick and relatively painless way to load their stylesheet statically and then use aphrodite to manage layout, etc?

What about bundling the server entry with webpack using target: 'node' option?
We'd have all the webpack loaders goodness on the server side without needing to hack node's require() or use webpack-isomorphic-tools.
Or is there a major problem or downside on this approach that I am not seeing? besides needing to have two webpack watches when developing

Edit: just saw it is already being done for prod, but why not dev too?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Jayphen picture Jayphen  ·  4Comments

ewolfe picture ewolfe  ·  4Comments

charlie632 picture charlie632  ·  4Comments

GouthamKD picture GouthamKD  ·  3Comments

dizzyn picture dizzyn  ·  3Comments