Repo: BeautyWe (A Star is Love)
A brief introduction
What is Beautywe.js?
It is a set of enterprise-level development paradigm focusing on wechat small programs, and its vision is:
Let the enterprise micro channel small program project code, more simple and beautiful.
Why do you name it that way?
Write beautiful code for wechat mini program by the beautiful we!
“We” is Both our We and wechat’s We, Both beautiful!
So what’s the selling point?
- Focus on the micro channel small program environment, write the original micro channel small program code.
- Because only focus on wechat small program, its source is also very simple.
- Plug-in programming makes complex logic easier to encapsulate.
- Plus some amenities:
- Some official plug-ins.
- A set of out-of-the-box frameworks containing engineering, project specifications and solutions to unique problems in the wechat applet environment.
- A CLI tool to help you quickly create applications, pages, components, etc.
It consists of the following parts:
-
A plug-in Core – BeautyWe Core for App, Page abstraction and packaging, maintain the traditional wechat small program development posture, while opening part of the native ability, so that it has the ability of “plug-in”.
-
Some official Plugins, BeautyWe Plugins, benefit from Core’s “plugability” feature, encapsulating complex logic and making it pluggable. Plugins are available for common requirements: enhanced storage, publish/subscribe, state machine, Logger, cache policy, etc.
-
The BeautyWe Framework describes an out-of-the-box project organization that integrates With BeautyWe Core and provides solutions such as global Windows, development specifications, multi-environment development, global configuration, and NPM.
-
A CLI tool – BeautyWe CLI provides command line tools for quickly creating applications, pages, plug-ins, and project building capabilities. Custom creation templates are also supported.
A simple example
download
Wrap your application in BeautyWe
After that, you can use the capabilities provided by the BeautyWe Plugin.
Open native App/Page, support plug-in
new BtApp({… }) results in wrapping the native application, including the “plug-in” processing, and then returning a new instance that matches the native App() method.
Here’s what plug-ins do.
First, pluginization opens up four capabilities of native apps:
-
The Data field merges the plug-in’s Data field into the native App’s Data field, which is easy to understand.
-
Native hook functions make native hook functions (such as onShow, onLoad) pluginable. Let native apps and multiple plug-ins listen to the same hook function at the same time. How it works is explained below.
-
The event hook function makes the event hook function (the hook function that interacts with the view layer) implement the same principle as the “native hook function”, although there are some differences in implementation.
-
Custom methods enable plug-ins to provide apis to consumers. To ensure that the API provided by the plug-in is elegant enough, support when calling the plug-in API (such as event plugin this.event. On (…)) ), API methods can still get native instances through this.
Pluginization of hook functions
Native hook functions, event hook functions are collectively called “hook functions”.
Internally, a Series Promise execution queue is maintained for each hook function.
OnShow, for example, would be executed like this:
Native. OnShow → plugina. onShow → pluginb. onShow →…
Here’s a closer look at how plugins work:
Here’s how it works:
- after
new BtApp(...)
Wrapper, all the hook functions have a separate execution queue, - We’ll start with the native hook functions
push
To the corresponding queue. Then eachuse
When a plugin is used, the plugin’s hook function is decomposed into the corresponding queuepush
. - when
Native App
(native) When a hook is triggered,BtApp
Functions in the corresponding queue are executed sequentially in the form of a Promise Series. - Special,
onLaunch
和onLoad
An initialized task is inserted at the top of the queue.initialize
), which is executed sequentially in a synchronous mannerInitialize Queue
The function inside. This is exactly what happens in plug-in lifecycle functionsplugin.initialize
.
This design provides the following functions:
-
Plug-in. You simply insert the task into the event queue of the corresponding hook function.
-
Supports asynchrony. Since it is run as a Promise Series, one task returns a Promise, and the next task waits for that task to complete before starting. If an error occurs, it is passed to the native onError().
-
Solve the getApp() === undefinded problem in wechat small program app.js. The essence of this problem is that the native instance was not created when App() was created. But because the Promise is a microtask in the Event loop, it is registered in the next loop. So App() is already done by the time the Promise is executed.
Some official plugins
BeautyWe officially offers a number of plug-ins:
- Enhanced Storage: Storage
- Data List: List Page
- Cache policy: Cache
- Log: Logger
- Event publish/subscribe: Event
- Status machine: Status
They are very simple to use, plug in where you need to. For space reasons, here are a few more interesting ones to talk about, and more of them can be found in the official documentation: BeautyWe
Enhanced Storage
This feature is provided by @beautywe/plugin-storage.
Because the original data storage life cycle of wechat mini program is consistent with the mini program itself, that is, except for the user’s active deletion or automatic cleaning over a certain period of time, otherwise the data is always available.
So the plugin provides two extensions based on wx.getStorage/setStorage:
- Overdue control
- Version of the isolation
Some simple examples
The installation
import { BtApp } from '@beautywe/core';
import storage from '@beautywe/plugin-storage';
const app = new BtApp();
app.use(storage());
Copy the code
Overdue control
// It will expire in 7 days
app.storage.set('name'.'jc', { expire: 7});Copy the code
Version of the isolation
app.use({ appVersion: '0.0.1' });
app.set('name'.'jc');
/ / return to jc
app.get('name');
// When the version is updated
app.use({ appVersion: 'hundreds' });
/ / return undefined;
app.get('name');
Copy the code
See @Beautywe /plugin-storage for more information
Data List List Page
For the very common business scenario of paging data lists, @Beautywe/plugin-ListPage provides a package:
- This applies to the common data list paging service scenario
- Support paging
- Support for multiple data lists
- Automatically capture pull-down reloads:
onPullDownRefresh
- Automatic capture pull-up loading:
onReachBottom
- Built-in request lock to prevent Parkinson’s shake users
- Simple and elegant API
A simple example:
import BeautyWe from '@beautywe/core';
import listpage from '@beautywe/plugin-listpage';
const page = new BeautyWe.BtPage();
// Use the listPage plugin
page.use(listpage({
lists: [{
name: 'goods'./ / data
pageSize: 20.// How many pieces of data per page, default 10
// The data source for each page. When the page is loaded each time, the function is called and the returned data is fetched.
fetchPageData({ pageNo, pageSize }) {
// Get data
return API.getGoodsList({ pageNo, pageSize })
// In some cases, dataCooker is a function you define for processing server data.
.then((rawData) = >dataCooker(rawData)); }}],enabledPullDownRefresh: true.// Enable pull-down reloading. Default is false
enabledReachBottom: true.// Enable pull-up loading. Default is false
}));
// Goods data will be loaded to the name defined above
// this.data.listPage.goods = {
// data: [...] // View layer, using this field to get specific data
// hasMore: true, // View layer, using this field to identify whether there is a next page
// currentPage: 1, // the view layer uses this field to identify the currentPage
// totalPage: undefined,
// }
Copy the code
Just tell the ListPage how to get the data, and it will automatically handle the pull-down reload, pull-up flip, and update the data to this.data.listPage.goods.
The View layer simply describes how the data is presented:
<view class="good" wx:for="listPage.goods.data">.</view>
<view class="no-more" wx:if="listPage.goods.hasMore === false">No more</view>
Copy the code
Listpage also supports multiple data lists and other configurations. For details, see @beautywe/ plugin-listPage
Cache policy Cache
@beautywe/plugin-cache provides a wechat applet side cache strategy, with super-cache providing the underlying support.
features
- This section provides a solution for the scenario where the server interface takes a long time but has high loading performance requirements
- Meet the most basic caching requirements, read (get) and save (set)
- Support for logical proxies for caches
- Flexible and configurable data storage modes
How it work
The usual form of request data is to fetch data from the server when the page loads, and then wait for the data to return and render the page:
However, in this mode, the loading performance may be affected by such factors as server interface time consumption and network environment.
We have many solutions for general Web development (such as server-side rendering, server-side caching, SSR, etc.) for pages that require high loading performance (such as the home page). However, there are some environments where this technology cannot be used (such as wechat applet).
Super Cache provides a solution for intermediate data caching:
Ideas:
- When you need to retrieve data, if there is a cache, give you the old data first.
- Then fetch new data from the server and flush the cache.
- If there is no cache at first, the server data is requested and returned.
- Next time you request the cache, start with step 1.
This solution, abandoned a little data real-time (not the first request, can only get the latest data), greatly improve the front-end loading performance. Suitable scene:
- Data real-time requirement is not high.
- The server interface takes a long time.
use
import { BtApp } from '@beautywe/core';
import cache from '@beautywe/plugin-cache';
const app = new BtApp();
app.use(cache({
adapters: [{
key: 'name',
data() {
return API.fetch('xxx/name'); }}]}));Copy the code
Suppose api.fetch (‘ XXX /name’) is the request server interface and returns data: datA_FROM_server
So:
app.cache.get('name').then((value) = > {
// value: 'data_from_server'
});
Copy the code
For more details, see @beautywe/plugin-cache
Log Logger
A lightweight log handling solution provided by @Beautywe/Logger-plugin that supports:
- Controllable log level
- Custom prefix
- Unified Log Processing
use
import { BtApp } from '@beautywe/core';
import logger from '@beautywe/plugin-logger';
const page = new BtApp();
page.use(logger({
// options
}));
Copy the code
API
page.logger.info('this is info');
page.logger.warn('this is warn');
page.logger.error('this is error');
page.logger.debug('this is debug');
/ / output
// [info] this is info
// [warn] this is warn
// [error] this is error
// [debug] this is debug
Copy the code
Level control
Which levels should be printed can be controlled by configuration:
page.use(logger({
level: 'warn',}));Copy the code
Logs above WARN (info, debug) will not be printed, which meets the different requirements of development and build environments for logs.
Level Levels are as follows:
Logger.LEVEL = {
error: 1.warn: 2.info: 3.debug: 4};Copy the code
For more configuration, see @beautywe/ plugin-Logger
BeautyWe Framework
@ beautywe/core and @ beautywe/plugin -… Applet provides:
- Open native, plug-in support — by Core
- Various plugins — by plugins
However, there are a lot of actual pain points in development that cannot be solved by the above two. Such as project organization, specification, engineering, configuration, multi-environment and so on
These are the categories that the BeautyWe Framework addresses.
As a set of out-of-the-box project frameworks, it provides these capabilities:
- Integrated BeautyWe Core
- NPM support
- Global window
- Global Page, Component
- Global configuration file
- Multi-environment development
- Example Pages
- Standard configuration required for normal projects: ES2015+, SASS, UGlify, Watch, etc
- And what we think are good project specifications (ESLint, commit log, directory structure, etc.)
Also because of space reasons, pick out a few interesting to talk about, more can see the official documentation: BeautyWe
Quickly create
First install @beautywe/ CLI
$ npm i @beautywe/cli -g
Copy the code
Create an
$ beautywe new app
> appName: my-app
>Version: 0.0.1
> appid: 123456
>Is this ok:
> {
> "appName": "my-app".
> "version": "0.0.1".
> "appid": "123456"
> }
Copy the code
After answering a few questions, the project is generated:
My-app ├── ├.js ├─ package.json ├─ app.js ├─ app.js ├─ app.js ├── My-App ├── ├.js ├─ ├.js ├─ app.javascript ├── Config ├─ Examples ├─ NPM ├─ pages ├─ project.config.jsonCopy the code
Create pages, components, plug-ins
page
- Main package page:
beautywe new page <path|name>
- Subcontracting page:
beautywe new page --subpkg <subPackageName> <path|name>
component
beautywe new component <name>
The plug-in
beautywe new plugin <name>
Custom Templates
In the./.templates directory, you have the create template for the quick create command:
$ tree .templates. Templates ├ ─ ─ component │ ├ ─ ─ index. The js │ ├ ─ ─ index. The json │ ├ ─ ─ index. The SCSS │ └ ─ ─ but WXML ├ ─ ─ page │ ├ ─ ─ index. The js │ ├ ─ ─ ├─ ├─ ├─ ├─ index.json │ ├─ ├─ index.txt ├─ index.txtCopy the code
The templates inside can be modified to accommodate project-level custom template creation.
Global window
We all know that wechat applet is a “single window” interactive platform, one page corresponds to one window. In business development, there are statements like this:
- Custom toast style
- Page bottom Copyright
- Global loading style
- Global hover control……
A slightly less elegant implementation could be to make separate components and then import each page. In this way, we will have a lot of repeated code, and every time a new page, we have to introduce again, late maintenance will be very tedious.
The concept of a “global window” is that you want all pages to have a place where global logic and interaction can go.
Global – the view components
This is a custom component, source at/SRC /components/global-view
WXML for each page needs only one layer at the top:
<global-view id="global-view">.</global-view>
Copy the code
Interactions, styles, and components that need to be implemented globally, it’s enough to maintain this component.
Global configuration file
In the SRC /config/ directory, you can store various global configuration files and run them in Node.js mode. (Thanks to node.js Power features).
Such as the SRC/config/logger. Js:
const env = process.env.RUN_ENV || 'dev';
const logger = Object.assign({
prefix: 'BeautyWe'.level: 'debug'}, {// Configuration of the development environment
dev: {
level: 'debug',},// Test environment configuration
test: {
level: 'info',},// Configure the online environment
prod: {
level: 'warn',
},
}[env] || {});
module.exports.logger = logger;
Copy the code
We can then read the config content as follows:
import { logger } from '/config/index';
// Logger. level will vary depending on the environment.
Copy the code
The Beautywe Framework integrates config into the getApp() example by default:
getApp().config;
Copy the code
Multi-environment development
The BeautyWe Framework supports multi-environment development with three preset policies:
- dev
- test
- prod
We can run the three build strategies with commands:
beautywe run dev
beautywe run test
beautywe run prod
Copy the code
The differences between the three sets of environments
The Beautywe Framework source code uses multiple environments by default in two ways:
- Build tasks (
gulpfile.js/env/...
) - Global configuration (
src/config/...
)
Differences in build tasks
Build tasks | instructions | dev | test | prod |
---|---|---|---|---|
clean | Clear dist file | Square root | Square root | Square root |
copy | Copy resource files | Square root | Square root | Square root |
scripts | Compiling JS files | Square root | Square root | Square root |
sass | Compile the SCSS file | Square root | Square root | Square root |
npm | Compile the NPM file | Square root | Square root | Square root |
nodejs-power | Compile the node.js file | Square root | Square root | Square root |
watch | Listening for file changes | Square root | ||
scripts-min | Compressed JS files | Square root | ||
sass-min | Compress SCSS files | Square root | ||
npm-min | Compress NPM files | Square root | ||
image-min | Compressed image file | Square root | ||
clean-example | Clear the sample page | Square root |
Node.js Power
Beautywe Framework code runs in two environments:
- Node.js runtime environment, such as build tasks.
- Wechat applet running environment, such as package to
dist
The code for the folder.
Operation process
Node.js Power is essentially a statically compiled implementation. Output the results of running a file in node.js environment to the running environment of wechat applet to meet specific needs.
Node.js Power will run a file named xxx.nodepower.js in the SRC directory of the project as Node.js. Write as a “literal object” to the corresponding xxx.nodepower.js file in the dist directory.
In the SRC/config/index. Nodepower. Js, for example:
const fs = require('fs');
const path = require('path');
const files = fs.readdirSync(path.join(__dirname));
const result = {};
files
.filter(name= >name ! = ='index.js')
.forEach((name) = > {
Object.assign(result, require(path.join(__dirname, `. /${name}`)));
});
module.exports = result;
Copy the code
This file, after being built by Node.js Power:
dist/config/index.nodepower.js
:
module.exports = {
"appInfo": {
"version": "0.0.1"."env": "test"."appid": "wx85fc0d03fb0b224d"."name": "beautywe-framework-test-app"
},
"logger": {
"prefix": "BeautyWe"."level": "info"}};Copy the code
This is enough to automatically package any configuration files you want to extend to the SRC /config/ directory.
Node.js Power has been integrated into dev, test, and Prod for multi-environment development.
Of course, you can run the build task manually:
$ gulp nodejs-power
Copy the code
NPM
The BeautyWe Framework implementation supports NPM in a simple way.
Package SRC/NPM /index.js with webpack and output to dist/ NPM /index.js in commonJS format
The benefits of this:
- Simple implementation.
- Make NPM packages centrally managed, and think twice each time you introduce dependencies to avoid flooding (especially in multiplayer development).
- use
ll dist/npm/index.js
Command to quickly see how much capacity NPM packages are taking up in a project.
Added NPM dependencies
In the SRC/NPM /index.js file, export:
export { default as beautywe } from '@beautywe/core';
Copy the code
Then in the other file import:
import { beautywe } from './npm/index';
Copy the code
More and more
Generally speaking, BeautyWe is a development paradigm for wechat applets.
Core and plugins extend native to provide encapsulation and pluggable use of complex logic.
The Framework is responsible for providing a set of enterprise-level project solutions for wechat small programs, out of the box.
For more information, visit our website: Beautywejs.com