Pesquisa de site

html - Ocorreu um erro durante a compilação do Widget do Azure DevOps: Não é possível resolver 'TFS/Dashboards/WidgetHelpers'


Sou iniciante em React e TypeScript. Você poderia me ajudar a entender o que está acontecendo com o meu código?

Arquivo HTML:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">

<head>
    <script type="text/javascript" src="../lib/VSS.SDK.min.js"></script>
    <script type="text/javascript">
        VSS.init({
            explicitNotifyLoaded: true,
            usePlatformStyles: true
        });
        // Entry point to widget
        VSS.require(["dist/Widget/Widget"], function () {
            VSS.notifyLoadSucceeded();
        });
    </script>
</head>

<body>
    <div id="root" class="widget"></div>
</body>

</html>

Arquivo TSX:

/// <reference types="vss-web-extension-sdk" />

import * as React from 'react';
import ReactDOM = require('react-dom');

import WidgetHelpers = require('TFS/Dashboards/WidgetHelpers');
import WidgetContracts = require('TFS/Dashboards/WidgetContracts');

interface IHelloWorldViewModelProps {
    name: string
}

export class HelloWorldViewModel extends React.Component<IHelloWorldViewModelProps> {
    render(): JSX.Element {
        return (
            <span>Hello, {this.props.name}</span>
        )
    }
}

export class Widget {

    public load(widgetSettings: WidgetContracts.WidgetSettings) {
        return this.render(widgetSettings);
    }

    private render(widgetSettings: WidgetContracts.WidgetSettings) : IPromise<WidgetContracts.WidgetStatus> {

        let userName = VSS.getWebContext().user.name;

        ReactDOM.render(
            <HelloWorldViewModel name={userName} />,
            document.getElementById('root'));

        return WidgetHelpers.WidgetStatusHelper.Success();
    }
}

WidgetHelpers.IncludeWidgetStyles();

VSS.register("Widget", function () {
    return new Widget();
});

webpack.config.js

const path = require("path");
const fs = require("fs");
const CopyWebpackPlugin = require("copy-webpack-plugin");

// Webpack entry points. Mapping from resulting bundle name to the source file entry.
const entries = {};

// Loop through subfolders in the "Samples" folder and add an entry for each one
const samplesDir = path.join(__dirname, "src");
fs.readdirSync(samplesDir).filter(dir => {
    if (fs.statSync(path.join(samplesDir, dir)).isDirectory()) {
        entries[dir] = "./" + path.relative(process.cwd(), path.join(samplesDir, dir, dir));
    }
});

module.exports = {
    target: "web",
    entry: entries,
    output: {
        filename: "[name]/[name].js"
    },
    devtool: "inline-source-map",
    devServer: {
        https: true,
        port: 3000,
        publicPath: "/dist/"
    },
    resolve: {
        extensions: [".ts", ".tsx", ".js"],
        alias: {
            "vss-web-extension-sdk": path.resolve("node_modules/vss-web-extension-sdk")
        },
    },
    stats: {
        warnings: false
    },
    module: {
        rules: [
            {
                test: /\.tsx?$/,
                loader: "ts-loader"
            },
            {
                test: /\.html$/,
                loader: "file-loader"
            },
            {
                test: /\.scss$/,
                use: ["style-loader", "css-loader", "azure-devops-ui/buildScripts/css-variables-loader", "sass-loader"]
            },
            {
                test: /\.css$/,
                use: ["style-loader", "css-loader"],
            }
        ]
    },
    plugins: [
        new CopyWebpackPlugin([{ from: "**/*.html", context: "src" }])
    ]
};

tsconfig.json

{
    "compilerOptions": {
        "charset": "utf8",
        "experimentalDecorators": true,
        "module": "amd",
        "moduleResolution": "node",
        "noImplicitAny": true,
        "noImplicitThis": true,
        "strict": true,
        "target": "es5",
        "rootDir": "src/",
        "outDir": "dist/",
        "jsx": "react",
        "lib": [
            "es5",
            "es6",
            "dom",
            "es2015.promise"
        ],
        "types": [
            "react"
        ]
    }
}

Ele me dá erro assim:

ERROR in ./src/Widget/Widget.tsx
Module not found: Error: Can't resolve 'TFS/Dashboards/WidgetHelpers' in 'D:\widget_example\src\Widget'
 @ ./src/Widget/Widget.tsx 12:0-46:2
i 「wdm」: Failed to compile.

Mas se eu remover as referências ao módulo WidgetHelpers, funciona bem:

/// <reference types="vss-web-extension-sdk" />

import * as React from 'react';
import ReactDOM = require('react-dom');

import WidgetHelpers = require('TFS/Dashboards/WidgetHelpers');
import WidgetContracts = require('TFS/Dashboards/WidgetContracts');

interface IHelloWorldViewModelProps {
    name: string
}

export class HelloWorldViewModel extends React.Component<IHelloWorldViewModelProps> {
    render(): JSX.Element {
        return (
            <span>Hello, {this.props.name}</span>
        )
    }
}

export class Widget {

    public load(widgetSettings: WidgetContracts.WidgetSettings) {
        return this.render(widgetSettings);
    }

    private render(widgetSettings: WidgetContracts.WidgetSettings) : boolean {

        let userName = VSS.getWebContext().user.name;

        ReactDOM.render(
            <HelloWorldViewModel name={userName} />,
            document.getElementById('root'));

        return true;
    }
}

VSS.register("Widget", function () {
    return new Widget();
});

Eu estava fazendo referência ao exemplo daqui

Você poderia, por favor, me indicar onde eu perdi alguma coisa?

Me avise se você precisar de informações adicionais.

Atualização 1

Consegui resolver o módulo TFS/Build/RestClient desta maneira:

/// <reference types="vss-web-extension-sdk" />

import * as React from 'react';
import ReactDOM = require('react-dom');

import WidgetHelpers = require('TFS/Dashboards/WidgetHelpers');
import WidgetContracts = require('TFS/Dashboards/WidgetContracts');
import AdoBuildClient = require('TFS/Build/RestClient');
import AdoBuildContracts = require('TFS/Build/Contracts');

let buildClient: AdoBuildClient.BuildHttpClient4;

VSS.require("TFS/Build/RestClient", function (AdoBuildClient: { getClient: () => AdoBuildClient.BuildHttpClient4; }) {
    buildClient = AdoBuildClient.getClient();
    buildClient.getDefinitions("MyFirstProject", "TestWidget").then(definitions => {
        console.log(definitions[0].id);
    })
});

...

Mas eu não entendo o que está acontecendo, o código virou uma bagunça mas funciona.

Atualização 2

O projeto que reproduz o problema pode ser encontrado aqui

Atualização 3

Os módulos TFS/... são carregados em tempo de execução, então acho que não há como resolvê-los durante a compilação. Eu removi a versão antiga do SDK vss-web-extension-sdk e movi meu projeto para a nova azure-devops-extension-sdk. Não há esses problemas na versão nova.

Resposta #1

Eu sei que isso pode parecer bobo, mas verifique novamente se o WidgetHelpers realmente está no caminho que você forneceu "TFS/Dashboards/WidgetHelpers". Eu já tive um problema onde precisei fazer um Salvar Como novamente para esse caminho, mas o erro que você recebeu "ERROR in ./src/Widget/Widget.tsx Module not found: Error: Can't resolve 'TFS/Dashboards/WidgetHelpers' in 'D:\widget_example\src\Widget' @ ./src/Widget/Widget.tsx 12:0-46:2 i (wdm): Failed to compile." é o .