使用 webpack dev server 和 rails server 的 Webpack 热重载

Posted

技术标签:

【中文标题】使用 webpack dev server 和 rails server 的 Webpack 热重载【英文标题】:Webpack hot reload using webpack dev server and rails server 【发布时间】:2019-10-29 14:33:18 【问题描述】:

我当前的应用程序是使用 Ruby on Rails 和 React/Typescript 设置的。我正在尝试设置热重载。

这是当前文件夹结构

Project Root
  - app => all the rails code
  - frontend => all the react code
  - webpack => list of configuration files, like development.js and production.js

此项目未使用 react_on_railswebpacker。前端代码与后端代码分开。 Rails 后端提供了一个 html

<div id='root' />

并且反应代码将运行。

这是我试图运行以使热重载工作的命令

node_modules/.bin/webpack-dev-server --config=./webpack/development.js  --hotOnly --entry=../frontend/Entry.tsx --allowedHosts=localhost:3000

但是,不仅热重载不起作用,我所做的更改也没有显示在浏览器中。一切看起来都在终端中。

我的问题是我在技术上同时运行两台服务器。

localhost:3000 => Rails server
localhost:8080 => Webpack dev server. 

如果我将 webpack 服务器也更改为指向 3000,rails 应用程序将无法正常工作。

有没有一种方法可以让我使用此设置进行热重载工作?

这里是 webpack 版本

"webpack": "^4.20.1",
"webpack-cli": "^3.1.1",
"webpack-dev-server": "^3.7.1" 

webpack.development.config.js

const webpack = require('webpack');
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin');

module.exports = 
  context: __dirname,
  entry: '../frontend/Entry.tsx',
  devtool: 'source-maps',
  resolve: 
    extensions: ['*', '.js', '.jsx', '.ts', '.tsx'],
    modules: [
      'node_modules',
      path.resolve(__dirname, '../frontend'),
      path.resolve(__dirname, '../node_modules')
    ]
  ,
  output: 
    path: path.join(__dirname, `../public/javascripts/`),
    publicPath: `/javascripts/`,
    filename: '[name]-[hash].js'
  ,
  module: 
    rules: [
      
        test: /\.(t|j)sx?$/,
        loader: 'ts-loader',
        options: 
          // disable type checker - we will use it in fork plugin
          transpileOnly: true
        
      ,
      
        enforce: 'pre',
        test: /\.(t|j)sx?$/,
        loader: 'source-map-loader'
      ,
      
        test: /\.css$/,
        use: ['style-loader', 'css-loader']
      ,
      
        test: /\.scss$/,
        use: ['style-loader', 'css-loader', 'sass-loader']
      ,
      
        test: /\.(png|svg|jpg|gif)$/,
        use: [
          
            loader: 'file-loader',
            options: 
              name: '[name]-[hash].[ext]',
              outputPath: 'images/'
            
          ,
          
            loader: 'image-webpack-loader',
            options: 
              pngquant: 
                quality: '40',
                speed: 4
              
            
          
        ]
      
    ]
  ,
  plugins: [
    new webpack.DefinePlugin(
      'process.env': 
        NODE_ENV: JSON.stringify('development')
      
    ),
    new HtmlWebpackPlugin(
      template: path.join(__dirname, '..', 'application.html'),
      filename: path.join(__dirname, '..', 'app', 'views', 'layouts', '_javascript.html.erb')
    ),
    // runs typescript type checker on a separate process.
    new ForkTsCheckerWebpackPlugin(
      checkSyntacticErrors: true,
      tsconfig: '../tsconfig.json'
    ),
    new CaseSensitivePathsPlugin()
  ],
  optimization: 
    splitChunks:  chunks: 'all' 
  
;

【问题讨论】:

【参考方案1】:

由于您是第一次设置 webpack 开发服务器,所以问题是双重的,

    设置 webpack 开发服务器 配置热重载

设置 webpack 开发服务器

我认为您的应用是 api 服务器。同样 webpack-dev-server 也是一个 http 服务器。它只是 expressjs 事实上的一个包装器。

在开发过程中使用 webpack 开发服务器时,捆绑包由 webpack 开发服务器提供服务,并且所有 xhr 请求都发送到该开发服务器。为了将这些请求路由到您的应用服务器,您需要将代理规则添加到您的 webpack 配置中。

在高层次上,流程如下所示。

browser ---(xhr requests)-----&gt; webpack-dev-server -----(proxy api requests)---&gt;app server


为了添加代理规则以将所有 api 请求路由到您的 rails 服务器,您的 api 路由应该以 /api 开头,例如 /api/customers 以便所有匹配 /api 的请求都转发到 rails 服务器

支持上述流程的示例配置将在您的 webpack 配置文件中如下所示

module.exports = 
  // ...your other configs
  devServer: 
    contentBase: path.join(__dirname, 'public/'),
    port: 8080,
    publicPath: 'http://localhost:8080/', // Path of your dev server
    historyApiFallback: true, // add this if you are not using browser router
    proxy: 
      '/api':  // string to look for proxying requests to api
        target: 'http://localhost:3000', // Path of your rails api server
      ,
    ,
  ,
  // ...your other configs


设置热重载

为了设置热重载,我建议使用 Dan Abramov 的react-hot-loader,因为它在 hmr 修补中的错误更少。

设置 hmr 很简单

    添加依赖yarn add react-hot-loader

    在你的 .babelrc 中添加 babel 插件

    
      "plugins": ["react-hot-loader/babel"]
    
    

    将您的根组件标记为热导出

    import  hot  from 'react-hot-loader/root'; // this should be imported before react and react-dom
    const App = () => <div>Hello World!</div>;
    export default hot(App);
    

注意:在您的依赖项中添加react-hot-loader 是安全的,因为在您的生产构建中。热重载包将被剥离。

要以热模式启动 webpack 服务器,您可以在 package.json 中添加如下脚本。

"scripts": 
    "start": "webpack-dev-server --hot --mode development --config ./webpack.dev.config"
  

【讨论】:

以上是关于使用 webpack dev server 和 rails server 的 Webpack 热重载的主要内容,如果未能解决你的问题,请参考以下文章

webpack之webpack-dev-server的使用

webpack5输入指令npx webpack-dev-server 使用webpack-dev-server报错

webpack-dev-server和webpack-dev-middleware的区别

使用 webpack dev server 和 rails server 的 Webpack 热重载

webpack learn1-webpack-dev-server的配置和使用3

如何使用 webpack-dev-server 和 html-webpack-plugin 观看 index.html