Some nonsense

After two months of silence, I came back.

As you can guess, I have been working as an intern in Tao Department for some time, and I have been putting more thought into my work since the last article. After the last post, I went to Tencent to intern for a while, waiting for the entry process of Ali interns to start.

After receiving the internship offer from Amoy Department, I bought the first air ticket in my life and took a plane for the first time. I came to a strange city — Hangzhou. Clean streets and spacious asphalt roads attracted me, a young man from a small city.

Blog has not updated for a long time, no matter personal website or nuggets, are rarely updated, occasionally on nuggets to see some good articles, always want to update, but did not find a good subject matter. Now, after a period of internship, I started to use the open source cross-end framework of Amoy — Rax, which is novel and fun. I also summarized some very basic development skills, and made up for the absence of official documents (official documents are really not very friendly for beginners).

Git repository: RAx-Todo

Git repository: software-engineering (also my course design, welcome everyone to click a Star)

The previous section is for those of you with little React background. Advanced players should click on Advanced Techniques

Project environment

  1. The node > = 10.3.0
  2. NPM > = 6.1.0

Front knowledge

  1. JSX
  2. Hooks
  3. TypeScript (optional)
  4. Jest (optional)
  5. Enzyme (optional)

Create a project

Initialize the project

This part of the official website documentation is more detailed, first take a look at the official website documentation: Fast Start

There are many solutions provided by the official website documents, which may be difficult to choose. We will start from the most basic TODO and use Rax to build a Web project:

npm init rax todo-list
Copy the code

Select project Type

After entering the above command, the RAx -CLI scaffolding tool will be installed using NPX. After installation, the following interface will appear:

Added 106 packages from 53 ficol3 in 10.5s? What's your project type? (Use arrow keys) ❯ App (Build Universal Application) Component (Build Universal Component) API (Build Universal API library) Plugin (Build plugin for miniapp)Copy the code

Use the up and down keys to move the arrow.

So let’s just go ahead and use the default options, create an APP, hit Enter.

Select an application running platform

? Choose targets your project want to run? (Press <space> to select, <a> to togg le all, < I > to Invert Selection) ❯◉ Web Infection was borne out of the Weex infection infection infection infection Kraken (Flutter) infection MiniApp Infection program of AlibabaCopy the code

Use the space bar to select, press the letter A to select all, here we choose Web first, if there is a need to compile Weex and small programs can be added in the project directory build.json.

The function of the Flutter application is not stable yet, and there are many pitfalls. It is recommended that players with good practical ability try it.

Select an Application Type

? What's your application type? (Only valid in target: Web/Weex/Kraken) (Use arr
ow keys)
❯ Single-page application (SPA)
  Multi-page application (MPA)
  Create lite application (The simplest project setup)
Copy the code

Select the type of APP, SPA or MPA. This option only applies to Web/Weex/Kraken(Flutter) applications.

We choose the default option SPA. For those who do not understand the difference between SPA and MPA, you can proceed to the article: Understanding single-page application (SPA) and multi-page application (MPA).

Enter the author name

? What's author's name? (rax) : on yiCopy the code

Choose a development language

? What type of language do you want to use? (Use arrow keys)
❯ JavaScript
  TypeScript
Copy the code

We’ll start with JavaScript, and if we need to import TypeScript later, we can do so manually.

Open the properties

? Do you want to enable these features? (Press <space> to select, <a> to toggle all, < I > to Invert selection) ❯ infection of server-side rendering (SSR) (Only valid in target: Web) infection Aliyun Function Compute (FaaS) (Only valid in target: Web) was borne out of infection infection with ReactCopy the code

We’re not going to pick anything here.

Of course, if necessary we can choose to configure Compatibility with React, we can also enable server side rendering (SSR) for our application. If you need to enable Serverless, you can also enable Function as a Service (FaaS). Both SSR and FaaS are valid only in Web applications.

Do not understand SSR and Serverless students please baidu (Google) ha.

Automatic installation dependency

? Do you want to install dependences automatically after initialization? (Y/n)
Copy the code

This option asks if the dependency is automatically installed after initialization. The default is Yes, so we don’t need to manually enter the project folder and execute NPM install.

Wait for the dependency installation to complete

To run your app:
   cd todo-list
   npm start
Copy the code

When this paragraph of text appears on the terminal, it means that the dependency installation is finished. We can enter the project folder and execute NPM start to start our project.

Start the project

After NPM start is executed, the terminal displays:

Rax development server has been started:

[Web] Development server at:
    http://localhost:3333/

Copy the code

At this point we can enter the Dev Server address in the browser and view our project.

To start developing

Select any IDE of your choice and enter the project folder. You will see a directory structure like this:

.├ ── ├─ ├─ download.txt # ├─ ├─ download.txt # ├─ ├─ download.txt # Download.txt # ├─ ├─ download.txt # Download.txt # Download.txt # Download.txt # Download.txt # download.txt # download.txt ├─ public # Static Resource Directory (Optional) Will copy the content to build directory ├ ─ ─ # components of the application of common components │ └ ─ ─ Logo # component │ ├ ─ ─ index. The CSS style # Logo components │ └ ─ ─ index. The JSX # Logo components JSX source code ├ ─ ─ the document # page's HTML template │ └ ─ ─ index. The JSX └ ─ ─ pages # page └ ─ ─ Home # Home page └ ─ ─ index. The JSXCopy the code

Before development, we need to know a few rules of Rax:

  • rpxDefault to:750rpxIs the screen width, i.e1rpx = 1/750 * screen width.
  • Style short: Not supported in Rax due to current compatibility issuesPart of theStyle abbreviation, for example: in writingborderWhen styling, you should separate the parts:border-width,border-style,border-color. In cases where attribute abbreviations don’t work on non-Web platforms, trying to separate attributes may solve the problem.

Delete the initial page

The first thing we need to do is remove the Logo component from the default Home page after the initial test. In the SRC/Components folder, remove the entire Logo component.

SRC /pages/Home/index.jsx: Hello World! .

// index.jsx
import { createElement } from 'rax';
import View from 'rax-view';
import Text from 'rax-text';

import './index.css';

export default function Home() {
  return (
    <View className="home">
      <Text>Hello World!</Text>
    </View>
  );
}
Copy the code

You’ll notice that the page changes to Hello World! The React application development method is used to start coding happily.

As you may see, why are we only using the View and Text components provided by Rax here?

Because in order to make the display consistent across platforms, Rax eliminates the problem of inconsistent style display across platforms for developers.

Of course, if you just want to make a Web application with Rax, you can use HTML tags.

The View and Text components can be used in the documentation: base component-view and base component-text

Create Item component

Depending on the degree of coupling, we should place the components in the SRC /pages/Home folder.

Under this folder, we create a directory like this:

SRC /pages/Home ├─ ├─ ├─ CSS # ├─ CSS # ├─ CSS #Copy the code

First we should think about which interfaces the ListItem should expose to the parent component:

  1. Each of these terms corresponds to thetaid
  2. The content of each item
  3. The completion status of each item
  4. Each itemonClickThe event

Once you know what interfaces the component should expose, you can start writing code:

// index.jsx
import { createElement } from 'rax';
import View from 'rax-view';
import Text from 'rax-text';

import './index.css';

const ListItem = (props) = > {
  // Deconstruct the id completion content onClick event
  const { id, done, content, onClick } = props;

  // Complete the item text style
  const style = {
    fontSize: '64rpx'.lineHeight: '96rpx'.textDecoration: done && 'line-through'
  };

  return (
    <View className="list-item" onClick={()= > onClick(id)}>
      <View className="list-dot"></View>
      <Text style={style}>{content}</Text>
    </View>
  );
};

export default ListItem;
Copy the code
/* index.css */
.list-item {
  flex-direction: row;
  justify-content: flex-start;
  align-items: center;
  width: 100%;
  height: 100rpx;
}

.list-dot {
  width: 20rpx;
  height: 20rpx;
  margin-right: 20rpx;
  border-radius: 10rpx;
  background-color: # 333;
}
Copy the code

Create a List component

Again, create a file:

SRC /pages/Home ├─ ├─ class # ├─ class # ├─ class # ├─ class # ├─ class # ├─ class # ├─ class # ├─ class # ├─ class # ├─ class # ├─ class # ├─ ├─ ├─ ├.txt # ├.txt # ├.txtCopy the code

Create a List component that acts as a container for ListItem to manage all items and add/remove them.

Since we want to add functions, the input box is definitely necessary. In the project we create, there is no input box component by default, so we need to install the input box component provided by Rax first:

npm install rax-textinput --save
Copy the code

The usage of the component can be referred to the documentation: base component -TextInput

// index.jsx
import { createElement, useState } from 'rax';
import View from 'rax-view';
import Text from 'rax-text';
import TextInput from 'rax-textinput';

import ListItem from '.. /ListItem';
import './index.css';

const List = () = > {
  // Initializes itemId +1 each time a new list item is added
  const [itemId, setItemId] = useState(0);
  // Initialize the list
  const [list, setList] = useState([]);
  // Initialize the TextInput content
  const [inputValue, setInputValue] = useState(' ');

  // Input box inputs events
  const handleUserInput = (e) = > {
    setInputValue(e.target.value);
  };

  // Add button click events
  const handleAddButtonClick = () = > {
    // Construct the list item data structure
    const item = {
      id: itemId,
      content: inputValue,
      done: false
    };
    The immutable idea generates new references
    const newList = [...list, item];
    setList(newList);
    // Empty the input field
    setInputValue(' ');
    // itemId ++
    setItemId(itemId + 1);
  };

  // List item click event
  const handleItemClick = (id) = > {
    // The traversal list is marked as completed when the event is not completed and deleted when the event is completed
    const newList = list.filter((item) = > {
      if (item.id === id) {
        if (item.done) {
          return false;
        } else {
          item.done = true; }}return true;
    });
    setList(newList);
  };

  return (
    <View className="list">
      <View className="list-input-wrapper">
        <TextInput
          className="list-input"
          value={inputValue}
          onInput={handleUserInput}
        />
        <View className="list-add-button" onClick={handleAddButtonClick}>
          <Text>add</Text>
        </View>
      </View>
      <View className="list-item-wrapper">
        {list.map((item) => (
          <ListItem
            key={item.id}
            id={item.id}
            content={item.content}
            done={item.done}
            onClick={handleItemClick}
          />
        ))}
      </View>
    </View>
  );
};

export default List;
Copy the code
.list {
  align-items: center;
}

.list-input-wrapper {
  flex-direction: row;
  justify-content: flex-start;
  align-items: center;
}

.list-add-button {
  justify-content: center;
  align-items: center;
  width: 150rpx;
  height: 100rpx;
  margin-left: 20rpx;
  border-radius: 10px;
  background-color: #dcdcdc;
}

.list-input {
  width: 100%;
  height: 100rpx;
  line-height: 96rpx;
  font-size: 64rpx;
  border-width: 1px;
  border-color: #dcdcdc;
}

.list-item-wrapper {
  width: 100%;
}
Copy the code

At this point, the basic functionality of the component is complete.

The introduction of the home page

Now we will introduce the component into the Home page:

import { createElement } from 'rax';
import View from 'rax-view';

import List from './components/List';
import './index.css';

export default function Home() {
  return (
    <View className="home">
      <List />
    </View>
  );
}
Copy the code

Now you can see a TODO application that performs the basic functions.

Advanced skills

I guess some of the best players will look at this and say,

Ah ~ you this so simple, is not a hand on the line ~

Once you say it, you really have hands.

The first part is for those of you who don’t read official documents or have only a few React basics. From this part, we will introduce some advanced content.

Modifying Route Configurations

In the project created above, you will see an app.json file in the project folder. Open it and you will see:

{
  "routes": [{"path": "/"."source": "pages/Home/index"}]."window": {
    "title": "Rax App"}}Copy the code

This file is used to control the routing of the project. If further development adds more pages, you need to add objects under Routes. Path is the access path (URL) of your newly added page, and source is the file directory of your newly added page.

Modify multi-page Application (MPA)

There is also a build.json file in the project folder that looks like this:

{
  "plugins": [["build-plugin-rax-app",
      {
        "targets": ["web"[}]]}Copy the code

Because when we created the project, we chose a single page application (SPA). What if we want to change to a multi-page application? Is simple:

Install multi-page app dependencies first:

npm install build-plugin-rax-multi-pages --save-dev
Copy the code

Then add a key “type” under the targets object with a value of “mpa” like this:

{
  "plugins": [["build-plugin-rax-app",
      {
        "targets": ["web"]."type": "mpa"}}]]Copy the code

When you restart Dev Server, the page looks like this:

Add cross-end support

We didn’t choose multi-platform when we first created the project, but Rax is a cross-platform development framework and there is a tutorial on how not to add cross-platform support (of course, it is more convenient to choose from the beginning).

Json file with targets array. If you want to add cross-end support, add the targets array to the target array:

{
  "plugins": [["build-plugin-rax-app",
      {
        "targets": ["web"."weex"."miniapp"."wechat-miniprogram"]."type": "mpa"}}]]Copy the code

Weex corresponds to weex platform, miniapp and weike-miniprogram correspond to ali miniprogram and wechat miniprogram.

View the Weex effect

When we use the above configuration in build.json, the page looks like this:

When you click on Weex Preview, you’ll find a bunch of JavaScript code. How do you Preview?

A slightly trickier way to do this is to first determine your Intranet IP address, change the localhost in the URL to the Intranet IP address, and then convert the URL to a QR code (Chrome has many plug-ins to do this).

Download Weex Playground on your phone and scan the QR code to preview the APP’s effects on your phone.

Weex Playground download address

TypeScript support

We didn’t introduce TypeScript in the previous project, so what if we wanted to?

It’s very simple, and it’s explained in the documentation on the official website: Project development – TypeScript support

Just install rax-types and typescript first:

npm install rax-types typescript --save-dev
Copy the code

To create the tsconfig.json file under the project folder, use the following configuration:

{
  "compilerOptions": {
    "module": "esNext"."target": "es2015"."outDir": "build"."jsx": "preserve"."jsxFactory": "createElement"."moduleResolution": "node"."sourceMap": true."alwaysStrict": true."baseUrl": "."."paths": {
      "rax": ["node_modules/rax-types"]}},"include": ["./src/**/*"]}Copy the code

Add TypeScript support.

Introducing automated testing

It was such a big hole that IT took me a whole morning to solve it.

There is no tutorial on automatic test configuration in the official Rax documents, so I had to directly seek help from the senior in charge of Rax maintenance in Dingding, and finally passed the test case after going through a lot of difficulties.

First, we need to install several dependencies, the number is a bit too many, recommend to install them separately:

npm install jest --save-dev
npm install @types/jest --save-dev
npm install @babel/preset-env --save-dev
npm install babel-jest --save-dev
npm install rax-test-renderer --save-dev
npm install @babel/plugin-proposal-class-properties --save-dev
npm install @babel/plugin-proposal-decorators --save-dev
npm install @babel/plugin-proposal-export-default-from --save-dev
npm install @babel/preset-flow --save-dev
npm install @babel/preset-react --save-dev
npm install babel-plugin-transform-jsx-stylesheet --save-dev
Copy the code

After the dependencies are installed, configure Babel by creating.babelrc.js in the project directory:

module.exports = function (api) {
  // Cache the returned value forever and don't call this function again.
  if (api) api.cache(true);

  return {
    presets: [
      '@babel/preset-flow'['@babel/preset-env',
        {
          loose: true}], ['@babel/preset-react',
        {
          pragma: 'createElement'}]],plugins: [
      '@babel/plugin-proposal-export-default-from'['@babel/plugin-proposal-class-properties', { loose: false}].'babel-plugin-transform-jsx-stylesheet'['@babel/plugin-proposal-decorators', { legacy: true}]],ignore: ['build'.'coverage'.'node_modules']}; };Copy the code

After configuration, Jest still won’t run. Add a startup script to package.json:

{
  "scripts": {
    "build": "build-scripts build"."start": "build-scripts start"."lint": "eslint --ext .js --ext .jsx ./".// Add the jest startup script
    "test": "jest"}}Copy the code

Also, configure Jest:

{
  "jest": {
    "collectCoverage": true."moduleNameMapper": {
      "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/__mocks__/fileMock.js"."\\.(css|less)$": "<rootDir>/__mocks__/styleMock.js"}}}Copy the code

After the configuration is added, create a folder under the project directory:

├─ ├─ garbage ├─ ├─ garbage ├─ garbage └─ garbage ├─ garbage ├─ garbageCopy the code

Add add code to both files:

// fileMock.js
module.exports = 'test-file-stub';
Copy the code
// styleMock.js
module.exports = {};
Copy the code

The purpose of configuring this section is to have Jest look under the mock folder when working with styles and static resources. Because the test script doesn’t actually access the introduced static resource at test time, it guides to the __mocks__ folder where it needs to reference the static resource, so it won’t report an error if the resource isn’t found. The configuration is obtained from the Jest official website to process static files.

Once configured, you can create a __test__ folder under the component you want to test and place the test scripts in that folder, or you can name the files with xxx.test. JSX, which will be recognized as test scripts by Jest.

In addition to Jest, the Rax team also provides an Enzyme adapter for Rax. Example project: RAxjs/Enzyme – Adapter-rax provides an example of how to use enzymes.

conclusion

Thanks to the strong technical strength of Amoy, the related ecology of Rax is relatively perfect. Also, the performance is very powerful, and I won’t cover it here.

Rax performs even better on applets than any other applets framework on the market: Rax — a twin-engine applets framework that perfectly blends compile and run time.

Other articles about Rax can be found on the blog.

At the end of this article, I would like to recommend my own public account: Hello FE, which is run by me and my fellow interns. We regularly share some dry goods.

At the same time, attention to the public number and front-end books a gift, welcome everyone to pay attention to, but also welcome everyone into the group communication: