使用 webpack 开发服务器和 rails 服务器的 Webpack 热重载
Webpack hot reload using webpack dev server and rails server
我当前的应用程序是在 Rails 和 React/Typescript 上使用 Ruby 设置的。我正在尝试设置热重载。
这是当前的文件夹结构
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_rails
或 webpacker
。前端代码与后端代码分开。 Rails 后端服务于 html
<div id='root' />
反应代码将 运行 关闭。
这是我尝试使用的命令运行让热重载工作
node_modules/.bin/webpack-dev-server --config=./webpack/development.js --hotOnly --entry=../frontend/Entry.tsx --allowedHosts=localhost:3000
但是,不仅热重载不起作用,我所做的更改也没有显示在浏览器中。终端中的一切看起来都一样。
我的问题是技术上我同时有两台服务器 运行ning。
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' }
}
};
由于您是第一次设置 webpack 开发服务器,所以问题有两方面,
- 设置 webpack 开发服务器
- 配置热重载
设置 webpack 开发服务器
我假设您的应用程序是 api 服务器。同样 webpack-dev-server 也是一个 http 服务器。实际上它只是 expressjs 的包装器。
在开发过程中使用 webpack dev server 时,bundle 由 webpack dev server 提供服务,并且所有 xhr 请求都向该 dev server 发出。为了将这些请求路由到您的应用服务器,您需要将代理规则添加到您的 webpack 配置中。
在高层次上,流程如下所示。
browser ---(xhr requests)-----> webpack-dev-server -----(proxy api requests)--->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"
}
我当前的应用程序是在 Rails 和 React/Typescript 上使用 Ruby 设置的。我正在尝试设置热重载。
这是当前的文件夹结构
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_rails
或 webpacker
。前端代码与后端代码分开。 Rails 后端服务于 html
<div id='root' />
反应代码将 运行 关闭。
这是我尝试使用的命令运行让热重载工作
node_modules/.bin/webpack-dev-server --config=./webpack/development.js --hotOnly --entry=../frontend/Entry.tsx --allowedHosts=localhost:3000
但是,不仅热重载不起作用,我所做的更改也没有显示在浏览器中。终端中的一切看起来都一样。
我的问题是技术上我同时有两台服务器 运行ning。
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' }
}
};
由于您是第一次设置 webpack 开发服务器,所以问题有两方面,
- 设置 webpack 开发服务器
- 配置热重载
设置 webpack 开发服务器
我假设您的应用程序是 api 服务器。同样 webpack-dev-server 也是一个 http 服务器。实际上它只是 expressjs 的包装器。
在开发过程中使用 webpack dev server 时,bundle 由 webpack dev server 提供服务,并且所有 xhr 请求都向该 dev server 发出。为了将这些请求路由到您的应用服务器,您需要将代理规则添加到您的 webpack 配置中。
在高层次上,流程如下所示。
browser ---(xhr requests)-----> webpack-dev-server -----(proxy api requests)--->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"
}