with TypeScript

Open File Explorer and create the (C:\temp\vscode) folder.
Create a new subfolder called "word-typescript" (C:\temp\vscode\word-typescript).
Open Visual Studio Code.
Display the Terminal window (View > Terminal).
Change to that folder.

cd C:\temp\vscode 

Install Yeoman

The Yeoman generator is an open source scaffolding tool for creating web applications.
This generator creates a Node.js project.

npm install -g yo                  // 3.1.1 
npm install -g generator-office // 1.7.8

check the versions and update if necessary.

yo --version 
npm view generator-office version

Generate Template Files

Run the Yeoman generator to create the project.

yo office 

Choose a project type: Select "Office Add-in Task Pane project using React framework".
SS


Choose a script type: Select "TypeScript".
What do you want to name your add-in: Type "Word-TypeScript".
Choose which office client application you want to target: Select "Word".
All the necessary files will then be created for you.
Open File Explorer and browse the following folder (C:\temp\vscode\
To open this folder in Visual Studio Code, type "code ."

code . 

manifest.xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<OfficeApp
  xmlns="http://schemas.microsoft.com/office/appforoffice/1.1"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:bt="http://schemas.microsoft.com/office/officeappbasictypes/1.0"
  xmlns:ov="http://schemas.microsoft.com/office/taskpaneappversionoverrides"
  xsi:type="TaskPaneApp">

<Id> Unique GUID </Id>
<Version>1.0.0.0</Version>
<ProviderName>Better Solutions Limited</ProviderName>
<DefaultLocale>en-US</DefaultLocale>
<DisplayName DefaultValue="Word-TypeScript"/>
<Description DefaultValue="A template to get started."/>
<IconUrl DefaultValue="https://localhost:3000/assets/icon-32.png"/>
<HighResolutionIconUrl DefaultValue="https://localhost:3000/assets/icon-80.png"/>
<SupportUrl DefaultValue="https://www.bettersolutions.com"/>
<AppDomains>
<AppDomain>bettersolutions.com</AppDomain>
</AppDomains>
<Hosts>
<Host Name="Document"/>
</Hosts>
<DefaultSettings>
<SourceLocation DefaultValue="https://localhost:3000/taskpane.html"/>
</DefaultSettings>
<Permissions>ReadWriteDocument</Permissions>
<VersionOverrides xmlns="http://schemas.microsoft.com/office/taskpaneappversionoverrides" xsi:type="VersionOverridesV1_0">
<Hosts>
<Host xsi:type="Document">
<DesktopFormFactor>
<GetStarted>
<Title resid="GetStarted.Title"/>
<Description resid="GetStarted.Description"/>
<LearnMoreUrl resid="GetStarted.LearnMoreUrl"/>
</GetStarted>
<FunctionFile resid="Commands.Url"/>
<ExtensionPoint xsi:type="PrimaryCommandSurface">
<OfficeTab id="TabHome">
<Group id="CommandsGroup">
<Label resid="CommandsGroup.Label"/>
<Icon>
<bt:Image size="16" resid="Icon.16x16"/>
<bt:Image size="32" resid="Icon.32x32"/>
<bt:Image size="80" resid="Icon.80x80"/>
</Icon>
<Control xsi:type="Button" id="TaskpaneButton">
<Label resid="TaskpaneButton.Label"/>
<Supertip>
<Title resid="TaskpaneButton.Label"/>
<Description resid="TaskpaneButton.Tooltip"/>
</Supertip>
<Icon>
<bt:Image size="16" resid="Icon.16x16"/>
<bt:Image size="32" resid="Icon.32x32"/>
<bt:Image size="80" resid="Icon.80x80"/>
</Icon>
<Action xsi:type="ShowTaskpane">
<TaskpaneId>ButtonId1</TaskpaneId>
<SourceLocation resid="Taskpane.Url"/>
</Action>
</Control>
</Group>
</OfficeTab>
</ExtensionPoint>
</DesktopFormFactor>
</Host>
</Hosts>
<Resources>
<bt:Images>
<bt:Image id="Icon.16x16" DefaultValue="https://localhost:3000/assets/icon-16.png"/>
<bt:Image id="Icon.32x32" DefaultValue="https://localhost:3000/assets/icon-32.png"/>
<bt:Image id="Icon.80x80" DefaultValue="https://localhost:3000/assets/icon-80.png"/>
</bt:Images>
<bt:Urls>
<bt:Url id="GetStarted.LearnMoreUrl" DefaultValue="https://go.microsoft.com/fwlink/?LinkId=276812"/>
<bt:Url id="Commands.Url" DefaultValue="https://localhost:3000/commands.html"/>
<bt:Url id="Taskpane.Url" DefaultValue="https://localhost:3000/taskpane.html"/>
</bt:Urls>
<bt:ShortStrings>
<bt:String id="GetStarted.Title" DefaultValue="Get started with your sample add-in!"/>
<bt:String id="CommandsGroup.Label" DefaultValue="Commands Group"/>
<bt:String id="TaskpaneButton.Label" DefaultValue="Show Taskpane"/>
</bt:ShortStrings>
<bt:LongStrings>
<bt:String id="GetStarted.Description" DefaultValue="Your sample add-in loaded succesfully.
             Go to the HOME tab and click the 'Show Taskpane' button to get started."/>
<bt:String id="TaskpaneButton.Tooltip" DefaultValue="Click to Show a Taskpane"/>
</bt:LongStrings>
</Resources>
</VersionOverrides>
</OfficeApp>

package.json file

Expand the Explorer pane on the left hand side.
Expand the project "Word-TypeScript".
Click on the package.json file.
SS


{ 
  "name": "office-addin-taskpane-react",
  "version": "0.0.1",
  "repository": {
    "type": "git",
    "url": "https://github.com/OfficeDev/Office-Addin-TaskPane-React.git"
  },
  "license": "MIT",
  "config": {
    "app-to-debug": "word",
    "app-type-to-debug": "desktop",
    "dev-server-port": 3000
  },
  "scripts": {
    "build": "webpack -p --mode production --https false",
    "build:dev": "webpack --mode development --https false",
    "dev-server": "webpack-dev-server --mode development",
    "lint": "office-addin-lint check",
    "lint:fix": "office-addin-lint fix",
    "prettier": "office-addin-lint prettier",
    "start": "office-addin-debugging start manifest.xml",
    "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",
    "validate": "office-addin-manifest validate manifest.xml",
    "watch": "webpack --mode development --watch"
  },
  "dependencies": {
    "core-js": "^3.1.4",
    "es6-promise": "^4.2.8",
    "office-ui-fabric-react": "^7.10.0",
    "react": "^16.8.2",
    "react-dom": "^16.8.2"
  },
  "devDependencies": {
    "@babel/core": "^7.11.6",
    "@babel/polyfill": "^7.11.5",
    "@babel/preset-env": "^7.11.5",
    "@types/find-process": "1.2.0",
    "@types/office-js": "^1.0.108",
    "@types/office-runtime": "^1.0.14",
    "@types/react": "^16.8.22",
    "@types/react-dom": "^16.8.4",
    "@types/react-hot-loader": "^4.1.0",
    "@types/webpack": "^4.4.34",
    "@types/webpack-dev-server": "^3.1.6",
    "babel-loader": "^8.1.0",
    "clean-webpack-plugin": "^3.0.0",
    "copy-webpack-plugin": "^6.1.1",
    "eslint-config-office-addins": "^1.0.19",
    "find-process": "^1.4.3",
    "css-loader": "^3.0.0",
    "eslint-plugin-office-addins": "^0.1.1",
    "eslint-plugin-react": "^7.16.0",
    "extract-text-webpack-plugin": "4.0.0-beta.0",
    "file-loader": "^4.2.0",
    "html-loader": "^0.5.5",
    "html-webpack-plugin": "^4.5.0",
    "less": "^3.9.0",
    "less-loader": "^5.0.0",
    "office-addin-cli": "^1.0.13",
    "office-addin-debugging": "^3.0.34",
    "office-addin-dev-certs": "^1.5.5",
    "office-addin-lint": "^1.0.26",
    "office-addin-manifest": "^1.5.12",
    "office-addin-prettier-config": "^1.0.12",
    "postcss-loader": "3.0.0",
    "react-hot-loader": "^4.12.6",
    "source-map-loader": "^0.2.4",
    "style-loader": "^0.23.1",
    "ts-loader": "^6.2.2",
    "typescript": "^4.0.3",
    "webpack": "^4.43.0",
    "webpack-cli": "^3.3.12",
    "webpack-dev-server": "^3.11.0"
  },
  "prettier": "office-addin-prettier-config"
}

webpack.config.js

const devCerts = require("office-addin-dev-certs"); 
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const HtmlWebpackPlugin = require("html-webpack-plugin");
const webpack = require('webpack');

const urlDev="https://localhost:3000/";
const urlProd="https://www.contoso.com/"; // CHANGE THIS TO YOUR PRODUCTION DEPLOYMENT LOCATION

module.exports = async (env, options) => {
  const dev = options.mode === "development";
  const buildType = dev ? "dev" : "prod";
  const config = {
    entry: {
      vendor: [
'react',
'react-dom',
'core-js',
'office-ui-fabric-react'
    ],
    taskpane: [
'react-hot-loader/patch',
'./src/taskpane/index.tsx',
    ],
    commands: './src/commands/commands.ts'
    },
    resolve: {
      extensions: [".ts", ".tsx", ".html", ".js"]
    },
    module: {
      rules: [
        {
          test: /\.tsx?$/,
          use: [
'react-hot-loader/webpack',
'ts-loader'
          ],
          exclude: /node_modules/
        },
        {
          test: /\.css$/,
          use: ['style-loader', 'css-loader']
        },
        {
          test: /\.(png|jpg|jpeg|gif)$/,
          loader: "file-loader",
          options: {
            name: '[path][name].[ext]',
          }
        }
      ]
    },
    plugins: [
      new CleanWebpackPlugin(),
      new CopyWebpackPlugin({
        patterns: [
        {
          to: "taskpane.css",
          from: "./src/taskpane/taskpane.css"
        },
        {
          to: "[name]." + buildType + ".[ext]",
          from: "manifest*.xml",
          transform(content) {
            if (dev) {
              return content;
            } else {
              return content.toString().replace(new RegExp(urlDev, "g"), urlProd);
            }
          }
        }
      ]}),
      new ExtractTextPlugin('[name].[hash].css'),
      new HtmlWebpackPlugin({
        filename: "taskpane.html",
          template: './src/taskpane/taskpane.html',
          chunks: ['taskpane', 'vendor', 'polyfills']
      }),
      new HtmlWebpackPlugin({
          filename: "commands.html",
          template: "./src/commands/commands.html",
          chunks: ["commands"]
      }),
      new webpack.ProvidePlugin({
        Promise: ["es6-promise", "Promise"]
      })
    ],
    devServer: {
      hot: true,
      headers: {
        "Access-Control-Allow-Origin": "*"
      },
      https: (options.https !== undefined) ? options.https : await devCerts.getHttpsServerOptions(),
      port: process.env.npm_package_config_dev_server_port || 3000
    }
  };

  return config;
};

src/taskpane/taskpane.html

This file contains the html code for the task pane.
Expand the "src" folder.
Expand the "taskpane" folder.
Click on the taskpane.html file.

<!DOCTYPE html> 
<html>

<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>React Task Pane Add-in</title>
<script type="text/javascript" src="https://appsforoffice.microsoft.com/lib/1.1/hosted/office.js"></script>
<link rel="stylesheet" href="https://static2.sharepointonline.com/files/fabric/office-ui-fabric-core/9.6.1/css/fabric.min.css"/>
<link href="taskpane.css" rel="stylesheet" type="text/css" />
</head>

<body class="ms-font-m ms-Fabric">
   <div id="container"></div>
</body>
</html>

src/taskpane/index.tsx

This file contains the typescript that sits behind the html page.

import "office-ui-fabric-react/dist/css/fabric.min.css"; 
import App from "./components/App";
import { AppContainer } from "react-hot-loader";
import { initializeIcons } from "office-ui-fabric-react/lib/Icons";
import * as React from "react";
import * as ReactDOM from "react-dom";

initializeIcons();

let isOfficeInitialized = false;

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

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

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

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

Other Project Files

The other project files are displayed on this page for reference.


Load the Add-in - Desktop

Execute the following command:

cd C:\temp\vscode\Word-TypeScript 
npm run start:desktop

This will start the local web server and open Word with the add-in loaded.
A small node window will be displayed.
A security warning dialog box will be displayed, asking you to install the certificate. Press Yes.
Select the Home tab and you will see a new group called "Commands Group" on the right hand side.
SS


?? and press the Run button.
When you have finished testing you need to execute the following command:

npm run stop 

Load the Add-in - Online

Execute the following command:

cd C:\temp\vscode\Word-TypeScript 
npm run start:web

This will start the debugging.
Allow localhost loopback for Microsoft Edge Web Browser: Select "Y".
A small node window will be displayed.
This will start the local web server.
The add-in will not appear automatically and will require side loading.


© 2022 Better Solutions Limited. All Rights Reserved. © 2022 Better Solutions Limited TopPrevNext