构建 IC Web 应用前端

Building a web frontend

Overview

The Internet Computer allows you to host frontends built with standard web technologies for your dapps, using our JavaScript agent as a communication layer. By using the asset canister provided by dfx to upload static files to the IC, you will be able to run your entire application on decentralized technology. This section takes a closer look at the default frontend template that is generated by running the dfx new command, configuring the frontend canister, and using other frameworks to build the user interface for your projects.  互联网计算机允许您使用我们的 JavaScript 代理作为通信层,托管使用标准网络技术为您的 dapp 构建的前端。 通过使用 dfx 提供的资产罐Canister将静态文件上传到 IC,您将能够在去中心化技术上运行整个应用程序。 本部分将详细介绍通过运行 dfx new 命令、配置前端容器以及使用其他框架为项目构建用户界面而生成的默认前端模板。

Here are some quick links to tutorials with example code for various stages of developing your frontend dapp:

How the default templates are used

As you might have noticed in the tutorials, guides, or sample code projects, by default each project created with dfx includes a template index.js and webpack.config.js file.

By default, the index.js file imports an agent that is located in src/declarations/project_frontend/ folder, where 'project' is your project's name (for this guide, the project's name is 'hello'). This directory will be generated by dfx when you run dfx deploy, either locally or when deploying to the IC.

The generated code for the agent will look like this:

src/declarations/hello_frontend/index.js:


import { Actor, HttpAgent } from "@dfinity/agent";

// Imports and re-exports candid interface
import { idlFactory } from "./hello_frontend.did.js";
export { idlFactory } from "./hello_frontend.did.js";

/* CANISTER_ID is replaced by webpack based on node environment
* Note: canister environment variable will be standardized as
* process.env.CANISTER_ID_<CANISTER_NAME_UPPERCASE>
* beginning in dfx 0.15.0
*/
export const canisterId =
process.env.CANISTER_ID_HELLO_FRONTEND ||
process.env.HELLO_FRONTEND_CANISTER_ID;

export const createActor = (canisterId, options = {}) => {
const agent = options.agent || new HttpAgent({ ...options.agentOptions });

if (options.agent && options.agentOptions) {
console.warn(
"Detected both agent and agentOptions passed to createActor. Ignoring agentOptions and proceeding with the provided agent."
);
}

// Fetch root key for certificate validation during development
if (process.env.DFX_NETWORK !== "ic") {
agent.fetchRootKey().catch((err) => {
console.warn(
"Unable to fetch root key. Check to ensure that your local replica is running"
);
console.error(err);
});
}

// Creates an actor with using the candid interface and the HttpAgent
return Actor.createActor(idlFactory, {
agent,
canisterId,
...options.actorOptions,
});
};

export const hello_frontend = createActor(canisterId);

Then, if you look at the src/hello_frontend/src/index.js file, you can see that it takes the generated actor, and uses it to make a call to the hello canister’s greet method:

import { hello_backend } from "../../declarations/hello_backend";

document.querySelector("form").addEventListener("submit", async (e) => {
e.preventDefault();
const button = e.target.querySelector("button");

const name = document.getElementById("name").value.toString();

button.setAttribute("disabled", true);

// Interact with foo actor, calling the greet method
const greeting = await hello_backend.greet(name);

button.removeAttribute("disabled");

document.getElementById("greeting").innerText = greeting;

return false;
});

In many projects, you will be able to use the code under declarations without any changes, then customize your dapp's frontend by making changes in src/hello_frontend/assets and src/hello_frontend/src. However, if your project has additional requirements, continue reading below.

Modifying the webpack configuration

Because webpack is a popular and highly-configurable module bundler for JavaScript-based applications, new projects create a default webpack.config.js file that makes it easy to add the specific modules, such as react and markdown, that you want to use.

Entry and output configuration

In many cases, you can use the default webpack.config.js file as-is, without any modification, or you can add plug-ins, modules, and other custom configuration to suit your needs. The specific changes you make to the webpack.config.js configuration largely depend on the other tools and frameworks you want to use.

For example, if you have experimented with the customizing the frontend or adding a stylesheet frontend tutorials, you might have modified the following section to work with React JavaScript:

        module: {
rules: [
{ test: /\.(ts|tsx|jsx)$/, loader: "ts-loader" },
{ test: /\.css$/, use: ['style-loader','css-loader'] }
]
}
};
}

If your application does not use dfx to run your build script, you can provide the variables yourself. For example:

DFX_NETWORK=ic NODE_ENV=production HELLO_CANISTER_ID=rrkah... npm run build

Ensuring node.js is available in a project

Because projects rely on webpack to provide the framework for the default frontend, you must have node.js installed in your development environment and accessible in the project directory.

  • If you want to develop your project without using the default webpack configuration and canister aliases, you can remove the frontend canister from the dfx.json file or build your project using a specific canister name. For example, you can choose to build only the hello program without frontend assets by running the following command:

    dfx build hello_backend
  • If you are using the default webpack configuration and running dfx build fails, you should try running npm install in the project directory then re-running dfx build.

  • If running npm install in the project directory doesn’t fix the issue, you should check the configuration of the webpack.config.js file for syntax errors.

Using other modules with the React framework

Several tutorials and sample projects in the examples repository illustrate how to add React modules using the npm install command. You can use these modules to construct the user interface components you want to use in your project. For example, you might run the following command to install the react-router module:

npm install --save react react-router-dom

You could then use the module to construct a navigation component similar to the following:

import React from 'react';
import { NavLink } from 'react-router-dom';

const Navigation = () => {
return (
<nav className="main-nav">
<ul>
<li><NavLink to="/myphotos">Remember</NavLink></li>
<li><NavLink to="/myvids">Watch</NavLink></li>
<li><NavLink to="/audio">Listen</NavLink></li>
<li><NavLink to="/articles">Read</NavLink></li>
<li><NavLink to="/contribute">Write</NavLink></li>
</ul>
</nav>
);
}

export default Navigation;

Iterate faster using webpack-dev-server

Starting with dfx 0.7.7, we now provide you with webpack-dev-server in our dfx new starter.

The webpack development server, webpack-dev-server, provides in-memory access to the webpack assets, enabling you to make changes and see them reflected in the browser right away using live reloading.

To take advantage of the webpack-dev-server:

  • Step 1: Create a new project and change to your project directory.

  • Step 2: Start the IC locally, if necessary, with the dfx start command.

    Then, deploy your dapp as you normally would, for example, by running the dfx deploy command.

  • Step 3: Start the webpack development server by running the following command:

     npm start
  • Step 4: Open a web browser and navigate to the asset canister for your application using port 8080.

    For example:

     http://localhost:8080
  • Step 5: Open a new terminal window or tab and navigate to your project directory.

  • Step 6: Open the src/hello_frontend/src/index.js file for your project in a text editor and make changes to the content.

    For example, you might add an element to the page using JavaScript:

    document.body.onload = addElement;

     document.body.onload = addElement;

    function addElement () {
    // create a new div element
    const newDiv = document.createElement("div");

    // and give it some content
    const newContent = document.createTextNode("Test live page reloading!");

    // add the text node to the newly created div
    newDiv.appendChild(newContent);

    // add the newly created element and its content into the DOM
    const currentDiv = document.getElementById("div1");
    document.body.insertBefore(newDiv, currentDiv);
    }
  • Step 7: Save your changes to the index.js file but leave the editor open to continue making changes.

  • Step 8: Refresh the browser or wait for it to refresh on its own to see your change.

    When you are done working on the frontend for your project, you can stop the webpack development server by pressing Control-C.

Using other frameworks

You may want to use a bundler other than webpack. Per-bundler instructions are not ready yet, but if you are familiar with your bundler, the following steps should get you going:

  • Step 1: Remove the copy:types, prestart, and prebuild scripts from package.json.

  • Step 2: Run dfx deploy to generate the local bindings for your canisters.

  • Step 3: Copy the generated bindings to a directory where you would like to keep them.

  • Step 4: Modify declarations/<canister_name>/index.js and replace process.env.<CANISTER_NAME>_CANISTER_ID with the equivalent pattern for environment variables for your bundler.

    • Alternately hardcode the canister ID if that is your preferred workflow
  • Step 5: Commit the declarations and import them in your codebase.

构建 IC Web 应用前端
arkMeta Crypto Network Limited, arkSong 2023年10月24日
标签
登录 留下评论

DIP20: 互联网计算机token铸造技术标准
DIP20: A fungible token standard for the DFINITY Internet Computer