npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

isomorphic-loader

v4.5.0

Published

Webpack isomorphic loader tools to make Node require handle files like images for Server Side Rendering (SSR)

Downloads

863

Readme

NPM version Build Status Dependency Status devDependency Status

Webpack Isomorphic Loader

Webpack loader and tools to make node.js require understands files such as images when you are doing server side rendering (SSR).

Purpose

With webpack and file-loader, you can do things like this in your React code:

import smiley from "./images/smiley.jpg";


render() {
    return <div><img src={smiley} /></div>
}

That works out nicely, but if you need to do SSR, you will get SyntaxError from node.js require. That's because require only understands JS files.

With this module, you can extend require so it understands these files.

It contains three parts:

  1. a webpack loader - to mark asset files
  2. a webpack plugin - collect asset files and generate mapping data
  3. a node.js library - extend require for SSR using the mapping data

Install

$ npm install isomorphic-loader --save

Usage

Configuring Webpack

First use the webpack loader isomorphic-loader to mark all your asset files that you want extendRequire to handle.

The webpack loader isomorphic-loader is just a simple pass thru loader to mark your files. It will not do anything to the file content.

Next install the webpack plugin IsomorphicLoaderPlugin to collect and save the list of the marked files.

For example, in the webpack config, to mark the usual image files to be understood by extendRequire:

const { IsomorphicLoaderPlugin } = require("isomorphic-loader");

module.exports = {
  plugins: [new IsomorphicLoaderPlugin()],
  module: {
    loaders: [
      {
        test: /\.(jpe?g|png|gif|svg)$/i,
        loader: "file!isomorphic"
      }
    ]
  }
};

You can also mark any file in your code directly:

import smiley from "file!isomorphic!./images/smiley.jpg";

Extending node.js require

With the marked asset files collected, initialize extendRequire with the mapping data before your server starts:

const { extendRequire } = require("isomorphic-loader");

const isomorphicRequire = extendRequire();

// isomorphicRequire is an instance of the ExtendRequire class exported from the module

// start your server etc

It will try to load the isomorphic config data from dist/isomorphic-assets.json. You can also pass in the config data:

extendRequire(options, require("./dist/isomorphic-assets.json"));

Custom Config Overrides

When calling extendRequire, you can pass in a callback in options.processConfig to override the isomorphicConfig

extendRequire({
  processConfig: config => {
    // do something with config
    return config;
  }
});

Activating and Deactivating extendRequire

  • deactivate API - deactivate extendRequire during run time.
  • activate API - activate extendRequire during run time.
const { extendRequire } = require("isomorphic-loader");

const isomorphicRequire = extendRequire();

isomorphicRequire.deactivate();

// and reactivate it

isomorphicRequire.activate();

Usage with CDN Server

If you publish your assets to a Content Delivery Network server, and if it generates a new unique path for your assets, then you likely have to set publicPath after webpack compiled your project.

That's why webpack's document has this note in the section about publicPath:

Note: In cases when the eventual publicPath of output files isn't known at compile time, it can be left blank and set dynamically at runtime in the entry point file. If you don't know the publicPath while compiling you can omit it and set __webpack_public_path__ on your entry point.

In that case, you would have to save the path CDN created for you and pass it to extendRequire with a custom config override, or you can just modify the config file directly.

If your CDN server generates an unique URL for every asset file instead of a single base path, then you have to do some custom post processing to update the asset mapping files yourself.

Webpack Dev Server

If you are using webpack dev server, then you probably have two separate processes running:

  1. webpack dev server (WDS)
  2. your app's node.js server (APP)

And IsomorphicLoaderPlugin would be running in WDS but extendRequire is in APP.

  • You need to setup some way to transfer the mapping data from WDS to APP.
  • When starting up, APP needs to wait for the first mapping data before actually startup, unless your SSR code is not loaded until it's actually invoked.

Here is an example using chokidar to transfer the data through a file:

  • In your webpack.config.js:
const fs = require("fs");
const { IsomorphicLoaderPlugin } = require("isomorphic-loader");

const isoPlugin = new IsomorphicLoaderPlugin();
isoPlugin.on("update", data => {
  fs.writeFileSync("./tmp/isomorphic-assets.json", JSON.stringify(data.config));
});

module.exports = {
  plugins: [isoPlugin]
};
  • In your app server index.js
const { extendRequire } = require("isomorphic-loader");

// figure out if running in dev mode or not
if (process.env.NODE_ENV !== "production") {
  const chokidar = require("chokidar");
  const assetFile = "./tmp/isomorphic-assets.json";

  let isomorphicRequire;

  function updateIsomorphicAssets() {
    const firstTime = !isomorphicRequire;
    if (firstTime) {
      isomorphicRequire = extendRequire();
    } else {
      // do the necessary require cache refresh so hot module reload works in SSR
    }

    isomorphicRequire.loadAssets(assetFile);
    if (firstTime) {
      startServer();
    }
  }

  const watcher = chokidar.watch(assetFile, { persistent: true });
  watcher.on("add", updateIsomorphicAssets);
  watcher.on("change", updateIsomorphicAssets);

  // do some timeout check
  setTimeout(() => {
    if (!isomorphicRequire) {
      console.error("timeout waiting for webpack dev server");
    }
  }, 20000).unref();
} else {
  extendRequire().loadAssets("./dist/isomorphic-assets.json");
  startServer();
}

License

Apache License, Version 2