Tutorial: Usar bibliotecas dependentes em um componente

[Este tópico faz parte da documentação de pré-lançamento e está sujeito a alterações.]

Este tutorial mostra como criar um componente de código para aplicativos controlados por modelos que dependem de bibliotecas contidas em outro componente. Saiba mais sobre a versão prévia das bibliotecas dependentes

Goal

Siga as etapas neste tutorial para criar um controle de biblioteca e um controle que depende dele. Este tutorial contém as seguintes etapas:

  1. Crie o componente de biblioteca: crie um componente que contenha apenas a biblioteca reutilizável. Para simplificar, esse controle contém apenas a biblioteca reutilizável. Não há razão para que ele também não pudesse fornecer funcionalidade.
  2. Crie o controle dependente: crie um componente que use a biblioteca definida no controle de biblioteca e adicione-o a uma forma de um aplicativo controlado por modelos para verificar se ele funciona.
  3. Carregar biblioteca dependente sob demanda: expanda o exemplo para fazer com que o componente dependente carregue o recurso de biblioteca sob demanda em vez de fazer com que a estrutura carregue a biblioteca quando o controle for carregado.

Pré-requisitos

Você já deve saber como:

1. Criar o componente de biblioteca

Esse componente não fornece recursos por si só. É simplesmente um contêiner para a biblioteca.

A primeira etapa é criar um novo componente usando o comando pac pcf init:

pac pcf init -n StubLibrary -ns SampleNamespace -t field -npm

Definir a biblioteca

  1. Você precisa de um novo arquivo de declaração (d.ts) para descrever os objetos e funções contidos em sua biblioteca. Crie um novo arquivo na pasta raiz do seu projeto chamado myLib.d.ts:

    declare module 'myLib' {
      export function sayHello(): string;
    }
    
  2. Vamos expor nossa biblioteca como um módulo UMD e precisamos colocar a variável no escopo global. Para isso, precisamos de um novo arquivo de declaração (d.ts). Crie um novo arquivo na pasta raiz do seu projeto chamado global.d.ts:

    /* eslint-disable no-var */
    declare global {
      var myLib: typeof import('myLib');
    }
    
    export { };
    
  3. Atualize tsconfig.json para permitir módulos UMD e código javascript da seguinte maneira:

    {
        "extends": "./node_modules/pcf-scripts/tsconfig_base.json",
        "compilerOptions": {
            "typeRoots": ["node_modules/@types"]
        }
    }
    

Adicionar a biblioteca

Em sua nova pasta de controle, adicione uma nova pasta para conter suas bibliotecas libs para este exemplo, crie um novo arquivo JavaScript. Este exemplo usa uma biblioteca chamada myLib-v_0_0_1.js que tem uma única sayHello função.

// UMD module pattern
var myLib = (function (exports) {
"use strict";

function sayHello() {
   return "Hello from myLib";
}

exports.sayHello = sayHello;

return exports;
})(/** @type {import('myLib')}  */ ({}));

Adicionar dados de configuração

  1. Adicione um arquivo nomeado featureconfig.json na pasta raiz do projeto.

  2. Adicione o seguinte texto ao featureconfig.json arquivo:

    {
      "pcfAllowCustomWebpack": "on",
      "pcfAllowLibraryResources": "on"
    }
    

    Saiba mais sobre o arquivo featureconfig.json

  3. Adicione um novo webpack.config.js arquivo na pasta raiz do projeto. Esses dados de configuração garantem que as bibliotecas não sejam agrupadas com a saída do controle. Não é necessário gerar um bundle, porque eles já são empacotados separadamente quando você compila o projeto.

    /* eslint-disable */
    "use strict";
    
    module.exports = {
      externals: {
        "myLib": "myLib"
      },
    }
    

    Saiba mais sobre o arquivo webpack.config.js

  4. Adicione uma referência à biblioteca sob o resources no manifesto de controle.

<resources> 
  <code path="index.ts" order="1"/> 
</resources> 

Adicionar a biblioteca à janela

A última etapa é editar o index.ts controle para associar a biblioteca à janela.

import { IInputs, IOutputs } from "./generated/ManifestTypes";

export class StubLibrary
implements ComponentFramework.StandardControl<IInputs, IOutputs>
{
 constructor() {
   // Empty
 }

 public init(
    context: ComponentFramework.Context<IInputs>,
    notifyOutputChanged: () => void,
    state: ComponentFramework.Dictionary,
    container: HTMLDivElement
 ): void {
   // Add control initialization code
 }

 public updateView(context: ComponentFramework.Context<IInputs>): void {
   // Add code to update control view
 }

 public getOutputs(): IOutputs {
    return {};
 }

  public destroy(): void {
    // Add code to cleanup control if necessary
  }
}

O projeto de biblioteca deve ter esta aparência:-

Exibição da pasta do projeto

Compilar e empacotar o componente da biblioteca

Para concluir o componente de biblioteca, conclua as seguintes etapas como de costume:

  1. Criar e compilar o componente de código
  2. Empacotar o componente de código
  3. Implante o componente de código.

2. Criar o controle dependente

Agora que você tem um controle de biblioteca, precisa de um controle para depender dele.

  1. Crie um novo componente usando este comando:

    pac pcf init -n DependencyControl -ns SampleNamespace -t field -fw react -npm
    
  2. Adicione um novo arquivo de controle de recurso na pasta raiz do seu projeto chamada featureconfig.json contendo o seguinte texto:

    {
      "pcfResourceDependency": "on"
    } 
    
  3. Adicione o recurso dependente no manifesto de controle.

    Use o schemaName do controle dependente [solution prefix]_[namespace].[control name], que você pode encontrar no arquivo solution.xml do componente dependente. O XML no arquivo solution.xml pode ter esta aparência:

    <RootComponents>
      <RootComponent
       type="66"
       schemaName="samples_SampleNamespace.StubLibrary"
       behavior="0"
      />
    </RootComponents>
    
<resources>
      <code path="index.ts"
         order="1" />
      <platform-library name="React"
         version="16.14.0" />
      <platform-library name="Fluent"
         version="9.46.2" />
</resources> 

Adicionar Global.d.ts

Como o StubLibrary é exposto como um módulo UMD, precisamos colocar a variável no escopo global. Para isso, precisamos de um novo arquivo de declaração (d.ts). Crie um novo arquivo na pasta raiz do seu projeto chamado global.d.ts:

/* eslint-disable no-var */

interface MyLib {
      sayHello(): string;
}

declare global {
      var myLib: MyLib;
}

export { };

Usar a função de biblioteca

Atualize o arquivo de componente HelloWorld.tsx para que ele use uma função da biblioteca dependente. A biblioteca é carregada no objeto Window em tempo de execução.

import * as React from 'react';
import { Label } from '@fluentui/react-components';

export interface IHelloWorldProps {
  name?: string;
}

export class HelloWorld extends React.Component<IHelloWorldProps> {
  public render(): React.ReactNode {
    return (
      <Label>
        {this.props.name}
      </Label>
    )
  }
}

Compilar e empacotar o componente dependente

Para concluir o componente dependente, conclua as seguintes etapas como de costume:

  1. Criar e compilar o componente de código
  2. Empacote o componente de código
  3. Implante o componente de código.

Adicionar o componente a um formulário

  1. Adicione o componente ao formulário controlado pelo modelo.

  2. Navegue até o formulário e você deverá ver o componente mostrar o texto Hello from myLib from Dependency.

    Imagem do componente em execução em um ambiente

3. Carregar a biblioteca dependente quando necessário

Você pode expandir este exemplo alterando o componente dependente para carregar o recurso de biblioteca sob demanda em vez de fazer com que a estrutura carregue a biblioteca quando o componente for carregado. O comportamento de carga sob demanda será útil se as bibliotecas que estão sendo usadas pelo controle forem grandes e aumentarem o tempo de carga do formulário.

Especificar o comportamento de carga sob demanda

Para especificar o comportamento de carga sob demanda, modifique o manifesto de controle do componente criado em 2. Crie o controle dependente.

<resources>
    <dependency type="control"
        name="samples_SampleNamespace.StubLibrary"
        order="1" />
    <code path="index.ts"
        order="2" />
    <platform-library name="React" version="16.14.0" />
    <platform-library name="Fluent" version="9.46.2" />
</resources>

Modificar o componente dependente para carregar a biblioteca sob demanda

Modifique o HelloWorld.tsx para adicionar um estado e métodos para atualizá-lo quando a dependência for carregada.

import * as React from 'react';
import { Label } from '@fluentui/react-components';

export interface IHelloWorldProps {
  name?: string;
}

export class HelloWorld extends React.Component<IHelloWorldProps> {
  public render(): React.ReactNode {
    return (
      <Label>
        { window.myLib.sayHello() + " from Dependency" || "Hello World"}
      </Label>
    )
  }
}

Atualizar index.ts

Quando o script é carregado sob demanda, você precisa fazer pequenos ajustes na forma como o componente é criado e inicializado. Por exemplo, novas variáveis para referências ao contexto e ao contêiner para atualizar o estado.

O mais importante é adicionar um getActions método para reagir ao On Load e solicitar que o controle dependente seja carregado.

import { IInputs, IOutputs } from "./generated/ManifestTypes";
import { HelloWorld, IHelloWorldProps } from "./HelloWorld";
import * as React from "react";

export class DependencyControl implements ComponentFramework.ReactControl<IInputs, IOutputs> {
    private notifyOutputChanged: () => void;

    constructor() {
        // Empty
    }

    public init(
        context: ComponentFramework.Context<IInputs>,
        notifyOutputChanged: () => void,
        state: ComponentFramework.Dictionary
    ): void {
        this.notifyOutputChanged = notifyOutputChanged;
    }

    public updateView(context: ComponentFramework.Context<IInputs>): React.ReactElement {
        const props: IHelloWorldProps = { name: 'Power Apps' };
        return React.createElement(
            HelloWorld, props
        );
    }

    public getOutputs(): IOutputs {
        return { };
    }

    public destroy(): void {
        // Add code to cleanup control if necessary
    }
}

Etapas finais

  1. Atualize o número da versão do controle em ControlManifest.Input.xml e a versão em Solution.xml
  2. Recompile, empacote, implante e publique a solução com o controle atualizado.

Verificar os resultados

Agora, quando a página é carregada, você vê a carga de controle com Loading... exibida.

Imagem do componente enquanto o formulário é carregado

Depois que a página carrega, o controle é atualizado para mostrar Hello from myLib Dependency On Demand Load.

Imagem do componente depois que o formulário for carregado

Bibliotecas Dependentes (versão prévia)