使用Node.js和Webpack构建dApp的后端

引导dApp开发经验 (Bootstrapping the dApp Development Experience)

Blockchain is a relatively young technology that is under continuous development. Similarly, applications built on the top of the blockchain are also still growing. As a result, there are several tools and best practices to streamline the development process. This tutorial will guide you through the steps to build a node.js back-end for a Decentralized Application (dApp). The tutorial introduces different developer tools and best practices and demonstrates how can we use them to boost the development experience.

区块链是一种相对年轻的技术,正在不断发展。 同样,构建在区块链顶部的应用程序仍在增长。 因此,有多种工具和最佳实践可简化开发过程。 本教程将指导您完成为分散式应用程序(dApp)构建node.js后端的步骤。 本教程介绍了不同的开发人员工具和最佳实践,并演示了如何使用它们来提升开发经验。

大图景 (The Big Picture)

A Decentralized Application (dApp) is a kind of web application whose back-end runs on a decentralized network such as Blockchain. The dApp has a traditional front-end built with HTML, CSS, and JavaScript. However, instead of connecting with a backend server, the dApp is connected to a blockchain node. The backend code of the dApp is written in the form of a smart contract using the Solidity programming language. The smart contract is a piece of program that contains the core logic of a dApp and is an integral part of the blockchain. The smart contracts are deployed using a locally running blockchain node and resides on the blockchain network.

去中心化应用程序(dApp)是一种Web应用程序,其后端运行在去中心化网络(例如区块链)上。 dApp具有使用HTML,CSS和JavaScript构建的传统前端。 但是,dApp不会连接到后端服务器,而是连接到区块链节点。 dApp的后端代码使用Solidity编程语言以智能合约的形式编写。 智能合约是一个程序,其中包含dApp的核心逻辑,并且是区块链的组成部分。 智能合约使用本地运行的区块链节点进行部署,并位于区块链网络上。

The communication between the front-end and the back-end is done through a Web3 JavaScript library. The Web3 is a collection of libraries which contains functionality to interact with the Ethereum ecosystem. The communication is essentially involved reading and writing the data from the blockchain through the smart contracts. A Web3 provider can be set up in both the frontend and the backend to send the transaction and listen to the blockchain events.

前端和后端之间的通信是通过Web3 JavaScript库完成的。 Web3是库的集合,其中包含与以太坊生态系统进行交互的功能。 通信本质上涉及通过智能合约从区块链读取和写入数据。 可以在前端和后端都设置Web3提供程序,以发送事务并侦听区块链事件。

教程的目标 (The Goal of the Tutorial)

The goal of the tutorial is to define a project structure to built a back-end for the dApp using node.js, truffle, and webpack. We will write a simple smart contract that will send some info to the blockchain and emit an event in the response of a successful transaction.

本教程的目标是定义一个项目结构,以使用node.js,truffle和webpack为dApp构建后端。 我们将编写一个简单的智能合约,该合约会将一些信息发送到区块链,并在成功交易的响应中发出事件。

The back-end will perform two main functions:

后端将执行两个主要功能:

  1. Publish transactions to the blockchain network

    将交易发布到区块链网络
  2. Listen to the blockchain events

    听区块链事件

开发者工具 (Developer Tools)

We will make use of the following tools:

我们将使用以下工具:

松露框架 (Truffle Framework)

We are using Truffle framework for the development of smart contracts. The Truffle provides a suite of tools to write smart contracts in Solidity, perform unit tests using Mocha and Chai, and deploy contracts on the Blockchain. Some of the most useful and frequently used truffle commands are:

我们正在使用Truffle框架来开发智能合约。 松露提供了一套工具,可以在Solidity中编写智能合约,使用Mocha和Chai执行单元测试以及在区块链上部署合约。 一些最有用且最常用的松露命令是:

  • Compile — truffle compile

    编译- truffle compile

  • Migrate — truffle migrate

    迁移- truffle migrate

  • Test contracts — truffle test

    测试合约— truffle test

You can find more from the official docs

您可以从官方文档中找到更多信息

伽纳彻 (Ganache)

We will make use of ganache to set up a private blockchain for the smart contract development, testing, and to speed up the overall iteration process. Furthermore, ganache comes with a built-in block explorer to examine blocks, transactions, contracts, and events to gain insight about what’s happening under the hood.

我们将利用ganache来建立私有区块链,用于智能合约的开发,测试,并加快整体迭代过程。 此外,ganache带有一个内置的区块浏览器,可以检查区块,交易,合同和事件,以了解幕后发生的事情。

Solidity漂亮插件 (Solidity Prettier Plugin)

Solidity Prettier automatically formats the Solidity files according to a predefined style guide.

Solidity Prettier会根据预定义的样式指南自动设置Solidity文件的格式。

Using Solidity prettier in combination with Solhint is quite effective as the prettier automatically fix many of the errors that Solhint finds, such as indentation and code styles.

将Solidity漂亮的东西与Solhint结合使用非常有效,因为漂亮的东西会自动修复Solhint发现的许多错误,例如缩进和代码样式。

林特— 索林特 (Linter — Solhint)

The Solhint is a great tool and library for the static analysis of Solidity code. Using Solhint will help us in automatic syntax checking and detect security vulnerabilities of the Solidity code.

Solhint是用于Solidity代码静态分析的出色工具和库。 使用Solhint将帮助我们进行自动语法检查并检测Solidity代码的安全漏洞。

Alternatively, you can use Ethlint.

另外,您可以使用Ethlint

松露单位测试 (Truffle Unit Test)

We will use the truffle unit testing to test the core functionality of our smart contract. Under the hood, Truffle uses the Mocha testing framework and Chai assertion library to write the tests in JavaScript.

我们将使用松露单元测试来测试我们智能合约的核心功能。 Truffle在后台使用Mocha测试框架和Chai断言库来用JavaScript编写测试。

实体代码覆盖率 (Solidity Code Coverage)

The Solidity coverage tool shows how much of the code-base has been covered and tested by the unit tests.

Solidity coverage工具显示单元测试已覆盖和测试了多少代码库。

燃气成本估算 (Gas Cost Estimation)

We will use ETH Gas Reporter to calculate gas and cost for the execution of functions and contract deployment. The market price data is fetched from Coin Market Cap and gas price is fetched from Eth Gas Station.

我们将使用ETH Gas Reporter来计算执行功能和合同部署所需的天然气和成本。 市场价格数据是从Coin Market Cap获取的,汽油价格是从Eth加油站获取的。

先决条件 (Prerequisites)

Install the following dependencies globally:

全局安装以下依赖项:

  • Truffle >= v5.0.41 ($ npm i truffle -g)

    松露 > = v5.0.41( $ npm i truffle -g truffle $ npm i truffle -g )

  • Node >= v10.16.3

    节点 > = v10.16.3

We will be using the CoinGecko free API to fetch the cryptocurrency prices.

我们将使用CoinGecko免费API获取加密货币价格。

项目结构 (Project Structure)

We will start with creating a new empty project directory dApp-nodeJS-webpack and inside the directory, we will initiate a npm project.

我们将首先创建一个新的空项目目录dApp-nodeJS-webpack然后在该目录内启动一个npm项目。

  • In your terminal type the following commands:

    在终端中,键入以下命令:
$ mkdir dApp-nodeJS-webpack && cd $_
$ npm init

This will create a package.json file that holds the metadata about the project such as project dependencies, purpose, version, and scripts, etc.

这将创建一个package.json文件,其中包含有关项目的元数据,例如项目依赖项,用途,版本和脚本等。

  • Create a new file index.js in the root directory. This file will call the overall functionality of the app by requiring the other modules.

    在根目录中创建一个新文件index.js 。 该文件将通过要求其他模块来调用应用程序的整体功能。

$ touch index.js

Add the following log statement to the newly created file:

将以下日志语句添加到新创建的文件中:

console.log('Hello world!')
  • To execute the functionality from the index.js file, add the following command to the scripts section of package.json file:

    要从index.js文件执行功能,请将以下命令添加到package.json文件的scripts部分:

"scripts": {
"app": "node index.js"
},

Now open a terminal inside the root directory and type the following command:

现在,在根目录中打开一个终端,然后键入以下命令:

npm run app

If you see the “Hello world!” in the console, you are good to go!

如果您看到“ Hello world!” 在控制台中,您一切顺利!

  • Inside the root directory, create a new directory app and inside that initiate a truffle project:

    在根目录中,创建一个新的目录app并在其中启动一个松露项目:

$ mkdir app && cd $_
$ truffle init

The result will look like the following terminal output:

结果将类似于以下终端输出:

At this point, your project should resemble to this GitHub commit.

此时,您的项目应类似于此GitHub commit

智能合约开发 (Smart Contract Development)

For the demo purpose, we are going to develop a simple Registration smart contract. The contract will allow the owner to register new users and only registered users will be able to send their values to the blockchain. Additionally, events will be emitted in the response of each successful transaction for user registration and send values.

出于演示目的,我们将开发一个简单的Registration智能合约。 该合同将允许所有者注册新用户,并且只有注册用户才能将其值发送到区块链。 此外,将在每次成功交易的响应中发出事件以进行用户注册并发送值。

智能合约剖析 (The Anatomy of the Smart Contract)

Let’s create a new file Registration.sol inside the contracts directory. The smart contract will start with specifying the version pragma. The pragma will specify the compiler version and is important to avoid the compatibility issues:

让我们在contracts目录中创建一个新文件Registration.sol 。 智能合约将从指定版本编译指示开始。 pragma将指定编译器版本,并且对于避免兼容性问题很重要:

pragma solidity >=0.5.0 <0.7.0;

Next, we can start by defining the contract itself. The first state variable we have to declare is the address to store the Ethereum address of the contract owner. We have specified the visibility of the variable as public to let other contracts to access it. We will assign the deployer address to the owner using constructor. The constructor will be executed only once at the time when the contract is created.

接下来,我们可以从定义合同本身开始。 我们要声明的第一个状态变量是address存储合同所有者的复仇地址。 我们已将变量的可见性指定为public以允许其他合同访问它。 我们将使用constructor将部署者地址分配给owner 。 合同创建时, constructor将仅执行一次。

contract Registration {
address public owner; constructor() public {
owner = msg.sender;
}
}

We create a struct User that has a bunch of attributes with which we will register a user.

我们创建一个结构User ,它具有一堆属性,我们将使用这些属性来注册用户。

struct User {
string name;
uint8 age;
bool registered;
}

We will declare two events NewUser and NewValue. These events will be triggered once the functions registerUser and send are executed, respectively.

我们将声明两个事件NewUserNewValue 。 一旦分别执行registerUsersend函数,将触发这些事件。

event NewUser(address userAddress, string name, uint8 age);
event NewValue(address userAddress, uint256 value);

The contract will use a mapping users to assign Ethereum address to User struct.

合同将使用映射users将以太坊地址分配给User结构。

mapping(address => User) public users;

We define a modifier onlyOwner to check if the function executes as expected or not. The use of onlyOwner modifier will allow only owner of the contract to register the new user.

我们定义了一个修饰符onlyOwner以检查函数是否按预期执行。 使用onlyOwner修饰符将仅允许合同所有者注册新用户。

modifier onlyOwner {
require(msg.sender == owner, "Only owner can register a user.");
_;
}

The contract contains two functions, registerUser and send. The registerUser will register a new user with the information specified in the User struct and bind the Ethereum address of the user with the struct. An event NewUser will be emitted if the function execution goes successful.

合同包含两个功能, registerUsersendregisterUserUser结构中指定的信息注册新用户,并将User的以太坊地址与该结构绑定。 如果函数执行成功,将发出事件NewUser

function registerUser(
address _address,
string memory _name,
uint8 _age
) public onlyOwner {
users[_address] = User(_name, _age, true);
emit NewUser(_address, _name, _age);
}

The send function will allow only registered users to send some random values to the blockchain by emitting an event on a successful transaction.

send功能将仅允许注册用户通过在成功交易中发出事件来向区块链发送一些随机值。

function send(uint256 _value) public {
require(
users[msg.sender].registered == true,
"Caller is not registered."
);
emit NewValue(msg.sender, _value);
}

坚固性和美观 (Solidity Linting and Prettier)

To boost the smart contract development experience, we will use Solidity linting and prettier tools. For dependency management, we will use node and npm. To do that, we will init a npm project inside the app directory using the command npm init. After that run the following command to install the solhint, prettier and prettier-plugin-solidity:

为了提高智能合约开发的经验,我们将使用Solidity棉绒和更漂亮的工具。 对于依赖关系管理,我们将使用nodenpm 。 为此,我们将使用命令npm initapp目录中初始化一个npm项目。 在此之后运行下面的命令来安装solhintprettierprettier-plugin-solidity

$ npm install solhint --save-dev
$ npm install --save-dev prettier prettier-plugin-solidity

Next, we need to add the following script to package.json file located inside the app directory to run the prettier on all the contracts inside the contracts directory:

接下来,我们需要将以下脚本添加到位于app目录内的package.json文件中,以便在contracts目录内的所有合同上运行更漂亮的脚本:

"prettier": "prettier --write **/*.sol"

After that, run the following command to apply prettier to our smart contracts:

之后,运行以下命令将更漂亮的内容应用于我们的智能合约:

$ npm run prettier

The output will look like the following:

输出将如下所示:

> prettier --write **/*.solcontracts/Migrations.sol 246ms
contracts/Registration.sol 199ms

For linting, we can use a .solhint.json file to configure Solhint linter for the whole project. Type the following command to generate a sample .solhint.json file:

对于棉绒,我们可以使用.solhint.json文件为整个项目配置Solhint linter。 键入以下命令以生成样本.solhint.json文件:

$ npx solhint --init

Populate the newly created JSON file with the following rulesets:

使用以下规则集填充新创建的JSON文件:

{
"extends": "solhint:recommended",
"plugins": [],
"rules": {
"avoid-suicide": "error",
"avoid-sha3": "warn"
}
}

Finally, add the following script to the package.json file:

最后,将以下脚本添加到package.json文件:

"slint": "solhint \"contracts/**/*.sol\""

Run the following command to apply the linting:

运行以下命令以应用棉绒:

$ npm run slint

The output of the above will look be like this:

上面的输出将如下所示:

> solhint "contracts/**/*.sol"
contracts/Migrations.sol
6:20 warning Variable name must be in mixedCase var-name-mixedcase✖ 1 problem (0 errors, 1 warning)

松露单元测试 (Truffle Unit Tests)

Unit tests are an integral part of the development to test if a smart contract works as expected or not. We will write a truffle unit test in JavaScript. Under the hood, truffle uses Mocha testing framework and Chai assertion library. We will also use some additional assertions and utilities, especially for testing the events, by using truffle-assertions package.

单元测试是开发中不可或缺的一部分,用于测试智能合约是否按预期工作。 我们将使用JavaScript编写松露单元测试。 在底层,松露使用Mocha测试框架和Chai断言库。 通过使用truffle-assertions包,我们还将使用一些其他的断言和实用程序,尤其是用于测试事件的程序。

We will start by creating an empty JavaScript file registration.js inside the test directory.

我们将从在test目录内创建一个空JavaScript文件registration.js开始。

  • Install the truffle-assertion library and include this, along with contract artifacts, in the registration.js test file:

    安装松露断言库,并将其与合同工件一起包括在registration.js测试文件中:

$ npm i truffle-assertions --save-dev

and inside the test file, include these line:

在测试文件中,包括以下行:

const Registration = artifacts.require('Registration')
const truffleAssert = require('truffle-assertions')
  • Create basic layout of the test file as given below:

    创建测试文件的基本布局,如下所示:
contract('Registration', (accounts) => {})
  • We will set up some test variable and create a global instance of our smart contract before executing the tests:

    在执行测试之前,我们将设置一些测试变量并创建智能合约的全局实例:
  • Next, we will test the following functionality of the contract:

    接下来,我们将测试合同的以下功能:
  • registerUser function should be executed only by the owner and it should emit the NewUser event:

    registerUser函数应仅由所有者执行,并且应发出NewUser事件:

it('should register a new user', async () => {
let result = await contract.registerUser(user, name, age, {
from: owner,
})
// test event
truffleAssert.eventEmitted(result, 'NewUser', (ev) => {
return ev.userAddress == user && ev.name == name && ev.age == age
})
})
  • The registerUser function should fail if caller is not the owner:

    如果调用者不是所有者, registerUser函数应该失败:

it('should fail to register by non-owner', async () => {
await truffleAssert.reverts(
contract.registerUser(user, name, age, {
from: notOwner,
}),
)
})
  • A registered user should be able to call the send function:

    注册用户应该可以调用send函数:

  • An un-registered user should not allow to call the send function:

    未注册的用户不应允许调用send函数:

it('should fail to send value from un-registered user', async () => {
await truffleAssert.reverts(
contract.send(value, {
from: unregistered,
}),
)
})

写作迁移 (Writing Migrations)

Create a new file 2_deploy_contracts.js inside the migrations directory and add the following contents to it:

migrations目录中创建一个新文件2_deploy_contracts.js ,并向其中添加以下内容:

const Registration = artifacts.require('Registration')module.exports = function (deployer) {
deployer.deploy(Registration)
}

The above migration is short and clean. However, we will look another way to export the contract ADDRESS and ABI during the migration so that we can use this metadata later to create a contract instance. This is useful especially in the case while calling the contract methods.

上面的迁移是短暂而干净的。 但是,我们将寻找另一种在迁移过程中导出合同ADDRESSABI ,以便以后可以使用此元数据创建合同实例。 这在调用合同方法的情况下尤其有用。

Add the following code block to the migrations file and it will create a Metadata.js file in the src directory:

将以下代码块添加到迁移文件中,它将在src目录中创建Metadata.js文件:

配置开发网络 (Config Development Network)

  • Uncomment following lines inside the truffle-config.js file to set up a local development network:

    取消注释truffle-config.js文件中的以下几行以设置本地开发网络:

// development: {
// host: "127.0.0.1", // Localhost (default: none)
// port: 8545, // Standard Ethereum port (default: none)
// network_id: "*", // Any network (default: none)
// },
  • We need to install and run ganache-cli before executing the tests. Run the following command to install the ganache-cli as a development dependency:

    在执行测试之前,我们需要安装并运行ganache-cli 。 运行以下命令以将ganache-cli安装为开发依赖项:

$ npm i ganache-cli --save-dev

and then add the following scripts to the package.json file to run the ganache and test through npm:

然后将以下脚本添加到package.json文件中以运行ganache并通过npm test

"ganache": "ganache-cli -m 'electric gift gold bitter boring surface stumble swift peanut adult horse dish'",
"test": "truffle test"
  • Now open two terminals inside the app directory and then first run the ganache-cli:

    现在在app目录中打开两个终端,然后首先运行ganache-cli

$ npm run ganache

In the second terminal, run the test file:

在第二个终端中,运行测试文件:

$ npm run test

The result of the above command should look like this:

上面命令的结果应如下所示:

实体代码覆盖率 (Solidity Code Coverage)

Install the Solidity code coverage:

安装Solidity代码覆盖率:

$ npm install --save-dev solidity-coverage

and add this to the plugin array of truffle-config.js file:

并将其添加到truffle-config.js文件的plugin数组中:

module.exports = {
networks: {...},
plugins: ["solidity-coverage"]
}

Add the following script to scripts in the package.json file:

将以下脚本添加到package.json文件中的scripts

"coverage": "truffle run coverage"

Finally, run the command:

最后,运行命令:

$ npm run coverage

The output will contain the following code coverage metrics:

输出将包含以下代码覆盖率指标:

Eth Gas记者 (Eth Gas Reporter)

Install the Eth gas reporter by running the following command:

通过运行以下命令来安装Eth气体报告程序:

$ npm install --save-dev eth-gas-reporter

config the reporter in the truffle-config.js file as:

truffle-config.js文件中将报告程序配置为:

mocha: {
// timeout: 100000
reporter: 'eth-gas-reporter',
reporterOptions: {
excludeContracts: ['Migrations'],
},
},

Now again run the npm run test command and the output will be like this:

现在再次运行npm run test命令,输出将如下所示:

At this point, your project may look like to this GitHub commit.

此时,您的项目可能看起来像是GitHub commit

后端开发 (Backend Development)

The back-end of the application is developed as a Node.js application. The application is developed using the JavaScript class and ES6syntax. The following snippet shows the node.js modules developed for the back-end.

该应用程序的后端被开发为Node.js应用程序。 该应用程序是使用JavaScript classES6语法开发的。 以下代码片段显示了为后端开发的node.js模块。

部署合同 (Deploy Contract)

Run the following command inside the app directory:

app目录中运行以下命令:

truffle migrate --reset --compile-all

The above command will generate the Metadata.js file in the src directory. The contains contract ADDRESS and ABI.

上面的命令将在src目录中生成Metadata.js文件。 包含合同ADDRESSABI

模组 (Modules)

Let’s create another directory src inside the app directory that will serve as a container for our modules. The backend will contain the following modules:

让我们在app目录中创建另一个目录src ,它将用作我们模块的容器。 后端将包含以下模块:

  • Provider: A web3 provider is required to set up a connection with an Ethereum node, create the instance of the contract, and to call the methods from the smart contract. For that, install web3 as project dependency by running the following command:

    Provider :需要一个web3提供程序来建立与以太坊节点的连接,创建合约实例,并从智能合约中调用方法。 为此,通过运行以下命令将web3安装为项目依赖项:

$ npm install web3

Create a new file Provider.js and add the following code block to that:

创建一个新文件Provider.js并在其中添加以下代码块:

  • Contract.js: This module will return the instance of the smart contract. Create and add the following block of code to Contract.js file:

    Contract.js :此模块将返回智能合约的实例。 创建以下代码块并将其添加到Contract.js文件:

  • Methods: This module will contain the functions to call the methods from the smart contract. For the demo purpose, we will call the sendmethod at a 30 seconds time interval. The contents of Methods.js will look like the following:

    Methods :此模块将包含从智能合约调用方法的功能。 出于演示目的,我们将以30秒的时间间隔调用send方法。 Methods.js的内容如下所示:

  • index.js: Finally, call the contract methods from the index.js file:

    index.js :最后,从index.js文件调用合同方法:

const Registration = require('./app/src/Methods')
const registration = new Registration()
registration.registerUser()
registration.sendDataInterval()

Let’s open a terminal inside the root directory and run the following command:

让我们在根目录中打开一个终端,然后运行以下命令:

npm run app

As a result, you should see the transaction hash in the console.

结果,您应该在控制台中看到事务哈希。

The complete code can be found here.

完整的代码可以在这里找到。

Webpack集成 (Webpack Integration)

A webpack is a static modular bundler which treats all files and assets as modules and relies on a dependency graph. Using the dependency graph, webpack statistically traverses all modules and their dependencies to build the graph and finally generate a single JavaScipt file that contains code from all modules in the correct order.

Webpack是一个静态模块化捆绑器,它将所有文件和资产视为模块,并依赖于依赖关系图。 Webpack使用依赖关系图统计遍历所有模块及其依赖关系以构建关系图,并最终生成一个JavaScipt文件,该文件以正确的顺序包含所有模块的代码。

Webpack要点 (Webpack Main Points)

To integrate webpack into the project, let’s have a brief look at the main points of the webpack:

要将webpack集成到项目中,让我们简要了解一下webpack的要点:

  • Entry: This is the module that webpack uses to start building its internal dependency graph. From this module, webpack determines all other modules and libraries for the entry module and includes them in the graph until no dependency is left. For the current project, the entry point is index.js file

    条目:这是webpack用于开始构建其内部依赖关系图的模块。 Webpack从该模块中确定入口模块的所有其他模块和库,并将它们包括在图中,直到没有依赖性为止。 对于当前项目,入口点是index.js文件

  • Output: This property defines a location where webpack will generate the bundle and a name for the bundle file.

    输出:此属性定义webpack生成捆绑包的位置以及捆绑包文件的名称。
  • Loaders: This is the property that webpack uses to transform the source code of non-JavaScript modules before they are added to the dependency graph.

    加载程序:这是webpack用来在将非JavaScript模块的源代码添加到依赖关系图之前对其进行转换的属性。
  • Plugins: Plugins are helpful to do the tasks that loaders can’t do such as asset management, bundle minimization, and optimization, etc.

    插件:插件有助于完成加载程序无法完成的任务,例如资产管理,捆绑包最小化和优化等。
  • Mode: Mode property specifies built-in optimizations corresponding to each environment such as production, development, or none.

    模式:模式属性指定与每个环境(例如生产,开发或无)相对应的内置优化。

Webpack配置 (Webpack Configurations)

Webpack uses a special configuration file, webpack.config.js, that specifies how assets and files will be transformed to generate the specified output. From the configurations, the webpack starts from the entry point and resolves each module it encounters while building the dependency graph. The final output will be a small bundle of all the modules of the project.

Webpack使用一个特殊的配置文件webpack.config.js ,该文件指定如何转换资产和文件以生成指定的输出。 从配置中,Webpack从入口点开始,并解析在构建依赖关系图时遇到的每个模块。 最终输出将是项目所有模块的一小包。

First, we need to install webpack and webpack-cli as project dependency. Run the following command inside the root directory of the project:

首先,我们需要安装webpackwebpack-cli作为项目依赖项。 在项目的根目录中运行以下命令:

$ npm install webpack webpack-cli --save-dev

In the package.json file, we can create webpack tasks in the scripts section as follows:

package.json文件中,我们可以在scripts部分中创建webpack任务,如下所示:

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

In the above scripts, we have used --mode flag to create development and production builds. Finally, add the following minimum configurations to the webpack.config.js file:

在上面的脚本中,我们使用了--mode标志来创建developmentproduction版本。 最后,将以下最低配置添加到webpack.config.js文件:

Run the $ npm run dev command inside the root directory and notices dist directory as a result. Change the directory to dist and run the bundle using the following command:

在根目录中运行$ npm run dev命令,并注意dist目录。 将目录更改为dist并使用以下命令运行捆绑包:

$ node bundle.js

Make sure you have ganache running and the artifacts are updated. If you could see the same output as before (transaction hashes), congratulations! you are all done🎉🎉🎉

确保已运行ganache ,并且工件已更新。 如果您能看到与以前相同的输出(交易哈希),那么恭喜! 一切都完成了🎉🎉🎉

Let’s tweak some more configurations to make the development experience a breeze.

让我们调整一些更多的配置,以使开发经验变得轻而易举。

  • Add watch flag to enable hot reload every time a file change. Change the dev script from

    添加watch标志可在每次文件更改时启用热重载。 从更改dev脚本

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

to

"dev": "webpack --mode development --w",
  • Clean the dist folder before each build. For this, we need to install and configure the clean-webpack-plugin by using the following command:

    每次构建前dist清洁dist文件夹。 为此,我们需要使用以下命令来安装和配置clean-webpack-plugin

$ npm install --save-dev clean-webpack-plugin

Update the webpack.config.js by adding the following lines:

通过添加以下行来更新webpack.config.js

const { CleanWebpackPlugin } = require('clean-webpack-plugin');// other config, removed for brevityplugins: [
new CleanWebpackPlugin()
],

The complete project code can be found here.

完整的项目代码可以在这里找到。

Happy coding🎉🎉🎉

编码愉快🎉🎉🎉

翻译自: https://medium.com/oli-systems/building-dapps-backend-with-node-js-and-webpack-311cda224da5

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值