带有 React 的 Webpack:我缺少什么吗?

Webpack with React: is there something I am missing?

这个问题会有点长,但我需要解释上下文,请耐心等待。

我正在开发按以下方式构建的 Reacj/Ruby 应用程序:

<my_app>
 |
 |_____be/
 |     
 |_____fe/
 |     |
 |     |_____node_module/
 |     |_____public/
 |     |     |_____index.html    
 |     |     |_____index.jsx
 |     |     |_____index.test.js
 |     |     |_____bundle.js
 |     |_____src/
 |           |_____app/
 |           |     |_____app.jsx
 |           |     |_____app.test.js
 |           |     |_____app.css
 |           |_____contents/
 |           |     |_____contents.jsx
 |           |     |_____contents.test.js
 |           |     |_____contents.css
 |           |_____footer/
 |           |     |_____footer.jsx
 |           |     |_____footer.test.js
 |           |     |_____footer.css
 |           |_____header/
 |           |     |_____header.jsx
 |           |     |_____header.teste.js
 |           |     |_____header.css
 |           |_____package.json
 |           |_____index.jsx
 |           |_____index.test.js
 |           |_____index.css
 |_____config.ru
 |_____Gemfile
 |_____Gemfile.lock
 |_____integrations.json
 |_____package.json
 |_____webpack.config.js

它是纯 Ruby(没有 Rails,没有 Sinatra)和 ReactJS 的混合体,其中 appcontentsfooterreader 是 ReactJS 组件。这个想法是将后端 be 与前端 fe 完全分离,由 webpack 和 Rack 协调,我将在其中使用 fetch从 tye 后端获取动态数据。

该应用程序在与 Webpack 捆绑后,将由 Rack 运行。 Rack::Static 中间件将处理由 npm run build 构建的静态资产,我创建的 Ruby gem 会将 de frontend 进行的调用重定向到一组 PORO(Plain旧 Ruby 对象)将提供动态数据。如您所见,它是一个小型框架。我试图证明的一个概念。

到了fe里面就万事大吉了。当我进入它的目录并做 npm test 所有测试时 运行 很好,当我 运行 npm start 它 运行 也很好。

为了简化此测试,ReactJS 组件所做的只是写一个单词。像这样:

app.jsx

import React from 'react';
import './app.css';
import Header from '../header/header.jsx';
import Contents from '../contents/contents.jsx';
import Footer from '../footer/footer.jsx';

export default class App extends React.Component {
  render() {
    return (
      <div className="app">
        <Header />
        <Contents />
        <Footer />
      </div>
    );
  }
}

还有这个:

header.jsx

import React from 'react';
import './header.css';

export default class Header extends React.Component {
  render() {
    return (
      <p>Header</p>
    );
  }
}

这样,当我在 fe 中 运行 npm start 时,我在浏览器中(在 http://localhost:3000)看到的是

Header
Contents
Footer

好吧,到目前为止一切都很好。但我需要将前端应用程序与 Webpack 捆绑在一起。这是我的配置:

webpack.config.js

var path = require('path');

module.exports = {
    entry: path.resolve(__dirname, 'fe/src/') + '/index.js',
    output: {
        path: path.resolve(__dirname,'fe/public/'), 
        filename: 'bundle.js'
    },
    devServer: {
        inline: true,
        contentBase: './public',
        port: 3333
    },
    module: {
        loaders: [{
            test: /\.jsx?$/,
            exclude: /node_modules/,
            loader: 'babel-loader',
            query: {
                presets: ['es2015', 'react']
            }
        }]
    }
}

如您所见,我正在 fe/public 创建 bundle.js。我的 Rack::Static 配置为 fe/public 内的 index.html 服务于所有静态请求,而我的 gem 处理动态请求。

碰巧,尽管所有模块都已正确安装并且所有内容都已正确捆绑,但当我 运行 我的应用程序带有 rackup 时,我什么也看不到。没有错误,没有问题……也没有言语!只是一个空白的浏览器屏幕。

我到底错过了什么?

编辑:

package.json

{
  "name": "emerald_application",
  "title": "Emerald Framework Application",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "bootstrap": "^3.3.7",
    "fb": "^1.1.1",
    "react": "^15.4.2",
    "react-dom": "^15.4.2",
    "react-router": "^4.0.0"
  },
  "devDependencies": {
    "babel-cli": "^6.24.1",
    "babel-core": "^6.24.1",
    "babel-loader": "^7.0.0",
    "babel-preset-es2015": "^6.24.1",
    "babel-preset-react": "^6.24.1",
    "react-scripts": "0.9.5",
    "webpack": "^2.5.1",
    "webpack-dev-server": "^2.4.5"
  },
  "scripts": {
    "start": "npm run serve | npm run dev",
    "dev": "webpack-dev-server --progress --colors --port 8090"
  }
}

没有,我没用过create-react-app。但这不是问题,因为 fe 部分很好 运行,即 ReactJS 部分 运行 本身很好,我对 ReactJS 应用程序了解足够多,即使没有也可以创建它们create-react-app,还特么小

我通过对代码进行一些更改解决了这个问题。

首先,我编辑了webpack.config.js

webpack.config.js

var path = require('path');

module.exports = {
    entry: path.resolve(__dirname, 'fe/src/') + '/index.jsx',
    output: {
        path: path.resolve(__dirname, 'public'), // <<== THIS
        filename: 'bundle.js'
    },
    devServer: {
        inline: true,
        contentBase: './app',
        port: 3333
    },
    module: {
        loaders: [{
            test: /\.jsx?$/,
            exclude: [ "node_modules" ],
            loader: 'babel-loader',
            query: {
                presets: ['es2015', 'react']
            }
        }]
    }
}

如您所见,这将使 Webpack 将 bundle.js 文件放在我应用程序根目录的 public 目录中。之后,我在同一个 public 目录中创建了一个 index.html 文件。指向 fe/src 内的 index.html 会给图像和其他资源的路径带来很多麻烦,现在将把它们放在 public/resources 中,这样更容易引用它们创建的页面。我的 index.html 文件现在显示为:

index.html

<!DOCTYPE html>
<html>
  <head>
  </head>
  <body>
    <div id="root"></div>
    <script type="text/javascript" src="bundle.js"></script>
  </body>
</html>

执行此操作后,应用程序不再 运行ning。 Webpack 找不到已安装的节点模块。它们在 fe 目录中,然后我用

创建了一个符号链接
$ ln -sf fe/node_modules

然后 webpack 运行 非常好并创建了包。

这是我的主要目标,将前端完全隔离在 fe 目录中,同时能够从这个目录之外 运行 这个应用程序,我可以 运行 使用单个命令和单个进程的完整应用程序(后端和前端)。这将使 Heroku 和其他类似服务的部署更加容易。

感谢所有花时间帮助我的人。这是我的 Web 开发框架 运行ning 的最后一步。现在只是进一步改进它的问题。