javascript 在Microsoft Office加载项中使用React路由器

6ss1mwsb  于 2023-02-15  发布在  Java
关注(0)|答案(2)|浏览(215)

我正在构建一个Microsoft Office加载项并使用React。通常,Web上的导航是使用react-router-dom完成的。但是,我无法在index.js文件中初始化HashRouter,因为它只给我一个白色页。我不确定bug在哪里,因为调试Office应用程序极其困难。
有人遇到过同样的问题吗?

import App from "./components/App";
import { AppContainer } from "react-hot-loader";
import { initializeIcons } from "@fluentui/font-icons-mdl2";
import * as React from "react";
import * as ReactDOM from "react-dom";
import { Provider } from "react-redux";
import store from "./redux/store";
import { HashRouter as Router, Route } from "react-router-dom";

/* global document, Office, module, require */

initializeIcons();

let isOfficeInitialized = false;

const title = "Contoso Task Pane Add-in";

const render = (Component) => {
  ReactDOM.render(
    <AppContainer>
      <Provider store={store}>
        <Router>
          <Component title={title} isOfficeInitialized={isOfficeInitialized} />
        </Router>
      </Provider>
    </AppContainer>,
    document.getElementById("container")
  );
};

/* Render application after Office initializes */
Office.onReady(() => {
  isOfficeInitialized = true;
  render(App);
});

/* Initial render showing a progress bar */
render(App);

if (module.hot) {
  module.hot.accept("./components/App", () => {
    const NextApp = require("./components/App").default;
    render(NextApp);
  });
}

我试着将渲染方法更改为

const render = (Component) => {
  ReactDOM.render(
    <AppContainer>
      <Provider store={store}>
        <Router>
          <Route exact path="/" element={<Component title={title} isOfficeInitialized={isOfficeInitialized} />} />
        </Router>
      </Provider>
    </AppContainer>,
    document.getElementById("container")
  );
};

然而,这并不能解决问题。我使用的是react@17react-router-dom@6

13z8s7eq

13z8s7eq1#

强烈怀疑这是由于通过不安全的连接提供外接程序,这将呈现白色,并提供错误的小迹象,直到它得到修复。
确保通过安全(HTTPS)连接提供应用。除非通过安全连接提供Office加载项,否则将不会呈现这些加载项,并且响应应用不会默认通过本地安全连接提供。
如果你在你的机器上本地测试插件,你需要设置你的本地环境,以确保它像通过HTTPS一样安全。通常这包括生成安全证书和一些其他步骤,在this article中描述得很好。
幸运的是,Microsoft为您省去了一些麻烦,并提供了一些方便的库来简化此过程。
首先确保您已经安装了以下开发包:

"office-addin-debugging": "^4.6.7",
"office-addin-dev-certs": "^1.11.1"

其次,在package.json文件中,您需要修改启动脚本,使其能够像这样使用office-addin-debugging:

"scripts": {

    "start": "office-addin-debugging start manifest.xml", <---TRY THIS!
    "start:desktop": "office-addin-debugging start manifest.xml desktop",
    "start:web": "office-addin-debugging start manifest.xml web",
    "stop": "office-addin-debugging stop manifest.xml",
    "watch": "webpack --mode development --watch"
  },

第三,在package.json文件的scripts部分之前添加一个config部分,如下所示:

"config": {
    "app_to_debug": "excel",
    "app_type_to_debug": "desktop",
    "dev_server_port": 3000
  },
  "scripts": {

然后,从理论上讲,当你运行npm run start时,你会被提示安装安全证书,excel的一个示例会自动启动,最好是和你现在正在工作的插件一起...祝你好运!

**对于Next.JS用户:**如果你正在使用next.js构建一个插件,而不是仅仅响应,你仍然可以依赖office-add-in-dev-certs,但是你需要做一个额外的步骤,编写你自己的服务器。比听起来容易。简单地说,安装我上面提到的相同的office-addin-dev-certs包,添加一个名为server.js的文件到你的项目的根目录,并包含以下代码:

const { createServer } = require('https')
const { parse } = require('url')
const next = require('next')
const devCerts = require('office-addin-dev-certs')

const dev = process.env.NODE_ENV !== 'production'
const hostname = 'localhost'
const port = 3000
const app = next({ dev, hostname, port })
const handle = app.getRequestHandler()

app.prepare().then(async () => {
  const options = await devCerts.getHttpsServerOptions()

  createServer(options, async (req, res) => {
    try {
      const parsedUrl = parse(req.url, true)
      const { pathname, query } = parsedUrl

      if (pathname === '/a') {
        await app.render(req, res, '/a', query)
      } else if (pathname === '/b') {
        await app.render(req, res, '/b', query)
      } else {
        await handle(req, res, parsedUrl)
      }
    } catch (err) {
      console.error('Error occurred handling', req.url, err)
      res.statusCode = 500
      res.end('internal server error')
    }
  }).listen(port, err => {
    if (err) throw err
    console.log(`> Ready on https://${hostname}:${port}`)
  })
})
pbgvytdp

pbgvytdp2#

在德鲁·里斯的评论帮助下,我解决了这个问题,问题有两个方面:

  • BrowserRouter组件在Microsoft Office加载项中不起作用。我们需要改用HashRouter
  • 最新react-router-dom@6库中使用的路由模式不适用于Microsoft Office加载项中的react@17。我们需要改用react-router-dom@5,它使用<Switch />组件进行路由。

index.js中的代码如下所示:

import App from "./main/App";
import { AppContainer } from "react-hot-loader";
import { initializeIcons } from "@fluentui/font-icons-mdl2";
import { Provider } from "react-redux";
import store from "./store";
import * as React from "react";
import * as ReactDOM from "react-dom";
import { HashRouter } from "react-router-dom";

/* global document, Office, module, require */

initializeIcons();

let isOfficeInitialized = false;

const title = "Cool title";

const render = (Component) => {
  ReactDOM.render(
    <AppContainer>
      <Provider store={store}>
        <HashRouter>
          <Component title={title} isOfficeInitialized={isOfficeInitialized} />
        </HashRouter>
      </Provider>
    </AppContainer>,
    document.getElementById("container")
  );
};

/* Render application after Office initializes */
Office.onReady(() => {
  isOfficeInitialized = true;
  render(App);
});

/* Initial render showing a progress bar */
render(App);

if (module.hot) {
  module.hot.accept("./main/App", () => {
    const NextApp = require("./main/App").default;
    render(NextApp);
  });
}

实际路由在App.js中实现,如下所示:

import * as React from "react";
import PropTypes from "prop-types";
import { Switch, Route } from "react-router-dom";

function App() {
  return (
    <main>
      <h1>App Title</h1>
      <Stack>
        <Switch>
          <Route exact path="/">
            <div>Hello World</div>
          </Route>
          <Route exact path="/main">
            <div>Hello Main</div>
          </Route>
        </Switch>
      </Stack>
    </main>
  );
}

export default App;

App.propTypes = {
  title: PropTypes.string,
  isOfficeInitialized: PropTypes.bool,
};

相关问题