question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

implementation of HMR examples in ssr

See original GitHub issue

💬 Questions and Help

Loadable Components project is young, but please before asking your question:

  • Read carefully the README of the project
  • Search if your answer has already been answered in old issues

After you can submit your question and we will be happy to help you!

First of all, sorry for bad English. I try to implementation hmr in this example of ssr projects. However, It says

image

I think ‘<’ is part of <!doctype html> because this hot-update.json file does not exists. I don’t know why this is not working.

I searched every issues on this repo about hmr, it does not help. Can you update your example of ssr with hmr??

Edited, I think this codes need to find out where my bug is. Below is webpack, basically almost same with example of ssr codes in this repo.

import path from 'path'
import webpack from 'webpack'
import nodeExternals from 'webpack-node-externals'
import LoadablePlugin from '@loadable/webpack-plugin'
import MiniCssExtractPlugin from 'mini-css-extract-plugin'

const DIST_PATH = path.resolve(__dirname, 'public/dist')
const production = process.env.NODE_ENV === 'production'
const development =
  !process.env.NODE_ENV || process.env.NODE_ENV === 'development'

const getConfig = target => ({
  name: target,
  mode: development ? 'development' : 'production',
  target,
  entry: target === 'web' ? ['webpack-hot-middleware/client', `./src/client/main-${target}.js`] : [`./src/client/main-${target}.js`],
  module: {
    rules: [
      {
        test: /\.js?$/,
        exclude: /node_modules/,
        use: [
          {
            loader: 'react-hot-loader/webpack',
          },
          {
            loader: 'babel-loader',
            options: {
              caller: { target },
            },
          },
        ]
      },
      {
        test: /\.css$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
          },
          'css-loader',
        ],
      },
    ],
  },
  externals:
    target === 'node' ? ['@loadable/component', nodeExternals()] : undefined,
  output: {
    path: path.join(DIST_PATH, target),
    filename: production ? '[name]-bundle-[chunkhash:8].js' : '[name].js',
    publicPath: `/dist/${target}/`,
    libraryTarget: target === 'node' ? 'commonjs2' : undefined,
  },
  plugins: target === 'web' ? [new webpack.HotModuleReplacementPlugin(), new LoadablePlugin(), new MiniCssExtractPlugin()] : [new LoadablePlugin(), new MiniCssExtractPlugin()],
})

export default [getConfig('web'), getConfig('node')]

server main.js

if (process.env.NODE_ENV !== 'production') {
  /* eslint-disable global-require, import/no-extraneous-dependencies */
  const { default: webpackConfig } = require('../../webpack.config.babel')
  const webpackDevMiddleware = require('webpack-dev-middleware')
  const webpackHotMiddleware = require('webpack-hot-middleware')
  const webpack = require('webpack')
  /* eslint-enable global-require, import/no-extraneous-dependencies */

  const compiler = webpack(webpackConfig)

  app.use(webpackHotMiddleware(compiler))
  app.use(webpackDevMiddleware(compiler, {
    noInfo: true,
    publicPath: '/dist/web',
    writeToDisk: true,
    // writeToDisk(filePath) {
    //   return /dist\/node\//.test(filePath) || /loadable-stats/.test(filePath)
    // },
  }))
}

and some react-hot-loader codes in client, but this is not important.

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:2
  • Comments:12

github_iconTop GitHub Comments

1reaction
golubvladimircommented, Sep 20, 2019

@xkguq007 How to fix it ?

externals: ['@loadable/component', nodeExternals()],

ERROR in client.js from Terser
Unexpected character '@' [external "@loadable/component":1,0 [client.js:3235,17]
0reactions
xkguq007commented, Jun 17, 2020

I’ll leave my entire webpack codes. It works.

webpack.client.config.js

"use strict";

const path = require("path");
const webpack = require("webpack");
const { smart } = require("webpack-merge");
const nodeExternals = require("webpack-node-externals");
const LoadablePlugin = require("@loadable/webpack-plugin");
const { GenerateSW } = require("workbox-webpack-plugin");
const { BundleAnalyzerPlugin } = require("webpack-bundle-analyzer");

const common = require("./webpack.config");

function getPlugins(isProduction, target) {
  const ret = [new LoadablePlugin()];

  if (!isProduction) {
    ret.push(new webpack.HotModuleReplacementPlugin());
  } else {
    ret.push(new webpack.optimize.AggressiveMergingPlugin());
    if (target === "web") {
      ret.push(
        new GenerateSW(),
        new BundleAnalyzerPlugin({
          analyzerMode: "static",
          openAnalyzer: false,
          reportFilename: "../report.html"
        })
      );
    }
  }
  return ret;
}

function getEntry(isProduction, target) {
  const ret = [];
  if (!isProduction) {
    if (target === "web") {
      ret.push("webpack-hot-middleware/client");
    }
  }

  ret.push(`./srcs/client/${target}-index.tsx`);
  return ret;
}

const base = (isProduction, target) => {
  return {
    name: target,
    entry: getEntry(isProduction, target),
    externals:
      target === "web" ? undefined : ["@loadable/component", nodeExternals()],
    module: {
      rules: [
        {
          test: /\.(png|jpg|jpeg|gif|svg)$/,
          use: [
            {
              loader: "file-loader",
              options: {
                outputPath: "../",
                publicPath: "/static/",
                name: "images/[name].[hash:8].[ext]",
                emitFile: target === "web" ? true : false
              }
            }
          ]
        }
        // FIXME: svg url-loader로 사용 시 나오지 않아 우선 주석처리하였음.
        //
        // {
        //   test: /\.(svg)$/,
        //   use: {
        //     loader: 'url-loader',
        //     options: {
        //       limit: 10240, // 10kb

        //       outputPath: '../', // for fallback (file-loader)
        //       name: 'images/[name].[hash:8].[ext]', // for fallback (file-loader)
        //       publicPath: '/static/', // for fallback (file-loader)
        //       emitFile: target === 'web' ? true : false // for fallback (file-loader)
        //     }
        //   }
        // }
      ]
    },
    output: {
      publicPath: `/static/${target === "web" ? "js" : "node"}/`,
      path: path.resolve(__dirname, ".dist", target === "web" ? "js" : "node")
    },
    plugins: getPlugins(isProduction, target)
  };
};

module.exports = (env, argv) => {
  const isProduction = argv ? argv.mode === "production" : false;
  return [
    smart(common(isProduction, "web", false), base(isProduction, "web")),
    smart(common(isProduction, "node", false), base(isProduction, "node"))
  ];
};

webpack.server.config.js

const path = require("path");
const webpack = require("webpack");
const nodeExternals = require("webpack-node-externals");
const { smart } = require("webpack-merge");
const CopyPlugin = require("copy-webpack-plugin");
const TerserPlugin = require("terser-webpack-plugin");

const common = require("./webpack.config");

function getPlugins(isProduction) {
  const ret = [
    new CopyPlugin([
      // { from: 'static/images', to: 'images' }, moved to client file-loader, url-loader
      { from: "static/icons", to: "icons" }
    ])
  ];
  return ret;
}

const base = isProduction => {
  return {
    entry: "./srcs/index.ts",
    output: {
      path: path.resolve(__dirname, ".dist")
    },
    optimization: {
      minimizer: [
        new TerserPlugin({
          terserOptions: {
            output: { comments: false },
            keep_classnames: true,
            keep_fnames: true
          }
        })
      ]
    },
    plugins: getPlugins(isProduction),
    externals: [nodeExternals()],
    stats: "errors-only",
    bail: true
  };
};

module.exports = (env, argv) => {
  const isProduction = argv ? argv.mode === "production" : false;

  return smart(common(isProduction, "node", true), base(isProduction));
};

webpack.config.js

// const fs = require('fs');
const path = require("path");

const webpack = require("webpack");
const DotEnvPlugin = require("dotenv-webpack");
const TsconfigPathsPlugin = require("tsconfig-paths-webpack-plugin");
const MonacoWebpackPlugin = require("monaco-editor-webpack-plugin");

function getPlugins(isProduction) {
  const ret = [new DotEnvPlugin()];
  return ret;
}

module.exports = (isProduction, target, isServer) => {
  const env = {
    configFile: isServer ? "tsconfig.server.json" : "tsconfig.client.json"
  };
  const isTargetWeb = target === "web";

  return {
    mode: isProduction ? "production" : "development",
    target,
    output: {
      libraryTarget: isTargetWeb ? undefined : "commonjs2",
      filename: isProduction ? "[name].bundle.js" : "[name].bundle.js",
      chunkFilename: isProduction
        ? "[id].[chunkhash:8].bundle.js"
        : "[id].bundle.js"
    },
    resolve: {
      extensions: [".ts", ".tsx", ".js"],
      modules: [
        path.resolve(__dirname, "node_modules"),
        path.resolve(__dirname, "srcs")
      ],
      alias: {
        "react-dom": "@hot-loader/react-dom"
      },
      plugins: [new TsconfigPathsPlugin({ configFile: env.configFile })]
    },
    module: {
      rules: [
        {
          test: /\.css$/i,
          use: ["style-loader", "css-loader"]
        },
        {
          test: /\.ts(x?)$/,
          exclude: /node_modules/,
          use: [
            {
              loader: "babel-loader",
              options: {
                caller: { target, isServer, isProduction }
              }
            },
            {
              loader: "ts-loader",
              options: {
                transpileOnly: true,
                configFile: env.configFile
              }
            }
          ]
        }
      ]
    },
    plugins: [...getPlugins(isProduction), new MonacoWebpackPlugin()]
  };
};
Read more comments on GitHub >

github_iconTop Results From Across the Web

implementation of HMR examples in ssr · Issue #323 - GitHub
I try to implementation hmr in this example of ssr projects. However, It says. image. I think '<' is part of <!doctype html>...
Read more >
Implementation of HMR(Hot Module Replacement) to Angular ...
In this article, I would like to show you how to implement HMR-Hot Module Replecament to your Angular project.
Read more >
React HMR with SSR - Stack Overflow
I think the solve of this trouble is mechanism called HMR (hot module replacement), but setting up this is hard for me. What...
Read more >
Hot Module Replacement in Redux - Toptal
This is a minimal example of hot module replacement (or HMR) in a Redux application. The working demo code is hosted on GitHub....
Read more >
Hot Module Replacement - webpack
There are many other loaders and examples out in the community to make HMR interact smoothly with a variety of frameworks and libraries......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found