0

We're developing an Office Addin application with Nodejs server using typescript. In development, everything is fine. however, when we wanna take a build of the application on production mode and deploy its ./dist folder to azure, some js libraries are missing used in HTML files. I observed that the hashed names for js files are different than the hashed names in referenced HTML.

When we take a build in development mode like "npm run build:development" and deploy, there is no problem. the application works normally with no missing files. Why production mode build process gives different hashed file name for js as the development mode build process gives proper names?

/* eslint-disable no-undef */
const path = require("path");
const devCerts = require("office-addin-dev-certs");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");

const urlDev = "https://localhost:3000/";
const urlProd = "https://xxx.z13.web.core.windows.net/"; // CHANGE THIS TO YOUR PRODUCTION DEPLOYMENT LOCATION

async function getHttpsOptions() {
  const httpsOptions = await devCerts.getHttpsServerOptions();
  return { cacert: httpsOptions.ca, key: httpsOptions.key, cert: httpsOptions.cert };
}

module.exports = async (env, options) => {
  const dev = options.mode === "development";
  const config = {
    devtool: "source-map",
    entry: {
      polyfill: ["core-js/stable", "regenerator-runtime/runtime"],
      taskpane: "./src/taskpane/taskpane.ts",
      commands: "./src/commands/commands.ts",
      pms: "./src/taskpane/pms.ts",
      tocpane: "./src/taskpane/tocpane.ts",
      modelpane: "./src/taskpane/modelpane.ts",
      dialog: "./src/dialogs/dialog.ts",
    },
    output: {
      devtoolModuleFilenameTemplate: "webpack:///[resource-path]?[loaders]",
      clean: true,
    },
    resolve: {
      extensions: [".ts", ".tsx", ".html", ".js"],
    },
    module: {
      rules: [
        {
          test: /\.ts$/,
          exclude: /node_modules/,
          use: {
            loader: "babel-loader",
            options: {
              presets: ["@babel/preset-typescript"],
            },
          },
        },
        {
          test: /\.tsx?$/,
          exclude: /node_modules/,
          use: "ts-loader",
        },
        {
          test: /\.html$/,
          exclude: /node_modules/,
          use: "html-loader",
        },
        {
          test: /\.(png|jpg|jpeg|gif|ico)$/,
          type: "asset/resource",
          generator: {
            filename: "assets/images/[name][ext][query]",
          },
        },
      ],
    },
    plugins: [
      new HtmlWebpackPlugin({
        filename: "taskpane.html",
        template: "./src/taskpane/taskpane.html",
        chunks: ["polyfill", "taskpane"],
      }),
      new HtmlWebpackPlugin({
        filename: "pms.html",
        template: "./src/taskpane/pms.html",
        chunks: ["polyfill", "pms"],
      }),
      new HtmlWebpackPlugin({
        filename: "tocpane.html",
        template: "./src/taskpane/tocpane.html",
        chunks: ["polyfill", "tocpane"],
      }),
      new HtmlWebpackPlugin({
        filename: "modelpane.html",
        template: "./src/taskpane/modelpane.html",
        chunks: ["polyfill", "modelpane"],
      }),
      new HtmlWebpackPlugin({
        filename: "dialog.html",
        template: "./src/dialogs/dialog.html",
        chunks: ["polyfill", "dialog"],
      }),
      new CopyWebpackPlugin({
        patterns: [
          {
            from: "schema/*",
            to: "schema/[name][ext][query]",
          },
          {
            from: "assets/images/*",
            to: "assets/images/[name][ext][query]",
          },
          {
            from: "assets/css/jstree/default/*",
            to: "assets/css/jstree/default/[name][ext][query]",
          },
          {
            from: "manifest*.xml",
            to: "[name]" + "[ext]",
            transform(content) {
              if (dev) {
                return content;
              } else {
                return content.toString().replace(new RegExp(urlDev, "g"), urlProd);
              }
            },
          },
        ],
      }),
      new HtmlWebpackPlugin({
        filename: "commands.html",
        template: "./src/commands/commands.html",
        chunks: ["polyfill", "commands"],
      }),
    ],
    devServer: {
      headers: {
        "Access-Control-Allow-Origin": "*",
      },
      https: env.WEBPACK_BUILD || options.https !== undefined ? options.https : await getHttpsOptions(),
      port: process.env.npm_package_config_dev_server_port || 3000,
    },
  };

  return config;
};
praksis
  • 1
  • 1

2 Answers2

0

By default when a new solution is created by using the Yeoman generator you can find the following commands in the package.json file:

"build": "webpack --mode production",
"build:dev": "webpack --mode development",

As you can see webpack is used in both cases for building the solution. In that case you need to check out the webpack.config.js file where all instructions for building the solution by webpack is located. You might have noticed the parameter passed to webpack to instruct how to build it. The mode parameter can be set to production or development. In the config file all these two parameters are used to configure/bundle files. See https://webpack.js.org/concepts/ for more information how to configure webpack.

Eugene Astafiev
  • 47,483
  • 3
  • 24
  • 45
  • Thank you for the update @Eugene. Actually, although I've been working on webpack.config.js for 3 days, I couldn't find the root cause of the problem. i update the post and added my config file, it might be helpful... – praksis Mar 01 '23 at 13:38
  • Have you tried to compare the config file with a newly created solution? – Eugene Astafiev Mar 01 '23 at 14:13
0

Today, I had a chance to try it in a newly generated yeoman solution. The same issue has occurred for injecting jquery.

You can find what I did below:

  1. I generated a yeoman solution
  2. I changed the outDir section of tsconfig file like "outDir": "./dist"
  3. I created a scripts folder under the assets folder and copied jquery-1.10.2.min.js to the scripts folder
  4. I installed jquery type and library: npm install --save-dev @types/jquery, npm install --save jquery
  5. I added a script directive for jquery in taskpane.html:
<script type="text/javascript" src="../script/jquery-1.10.2.min.js"></script>
  1. Run npm run build

What I observed is that the generated js file name for jquery is

fbf8345c48a75d93bd35.js

But, the taskpane.html script tag regarding jQuery is like:

<script src="ba18c7bb8869bee98004.js"></script>

As you can see, because webpack gives wrong names, the application deployed in production mode get 404 error for imported javascript files (as indicated by Rick)

Tyler2P
  • 2,324
  • 26
  • 22
  • 31
praksis
  • 1
  • 1
  • I think that something is changing the bundles, and causing a new hash name to be generated, _after_ HtmlWebpackPlugin has injected the original hash-named files. This might be related to the interaction of the tsconfig.json file and "devtool" property in webpack.config.js. Look [here](https://webpack.js.org/configuration/devtool) for other possible values for "devtool". Try some of the others that have "yes" in the "production" column of the table. – Rick Kirkham Mar 03 '23 at 19:18