getting-started-with-gutenberg-block-development-wolfactive-949x475
06/06/2021

[Gutenberg] Cấu hình React vào plugin hỗ trợ viết block Gutenberg

Chào mọi người đến với Series lập trình block Gutenberg trong WordPress. Series này giành cho những bạn thích Wordpess nhưng muốn tìm cảm giác làm theme, giao diện WordPress theo hướng mới mẻ không bị nhàm chán, thích làm giao diện trong CMS và trang web với React.

Với bài lần trước mình đã giới thiệu tổng quan về series này. Thì bài viết này sẽ hướng dẫn các bạn tạo plugin và cấu hình React js vào plugin để hỗ trợ viết block Gutenberg

Khởi tạo plugin viết block Gutenberg

Trước tiên các bạn vào folder plugin của wordpress (wp-content/plugins) tạo folder plugin wa-gutenberg. Sau đó vào thư mục wa-gutenberg tạo file plugin.php và index.php`.

Trong file index.php các bạn sẽ để trống. Còn file plugin.php dùng để khai báo plugin với WordPress. Các bạn thêm đoạn này vào file.

/**
 * Plugin Name
 *
 * @author            Wolfactive
 * @wordpress-plugin
 * Plugin Name:       Wa Gutenberg
 * Plugin URI:        https://wolfactive.dev/
 * Description:       This plugin supports creating blocks Gutenberg
 * Version:           1.0.0
 * Requires at least: 5.2
 * Requires PHP:      7.3
 * Author:            Wolfactive
 * Author URI:        https://wolfactive.dev/
 * Text Domain:       wa-gutenberg
 * License:           GPL v2 or later
 * License URI:       http://www.gnu.org/licenses/gpl-2.0.txt
 */

Sau khi điền thông tin trên vào file các bạn vào dashboard plugin của wordpress.

plugin-ho-tro-viet-block-gutenberg

Và đây là thành quả, vậy là chúng ta đã hoàn thành xong bước khởi tạo plugin bước thứ sẽ cấu hình react vào plugin để hỗ trợ viết block gutenberg

Cấu hình React js hỗ trợ viết block Gutenberg

Để cấu hình react vào plugin các bạn tạo file package.json bằng cách bật terminal. Và gõ dòng lệnh sau npm init . Sau khi làm xong các bước mà terminal hướng dẫn các bạn đã có file package,json. Và lưu ý các bạn phải cài node js trước khi thức hiện.

Các ban copy đoạn code sau vào package.json

{
    "name": "wagutenberg",
    "version": "1.0.0",
    "description": "This is base source creating blocks Gutenberg by Wolfactive. It includes webpack, gulp,...",
    "main": "index.js",
    "scripts": {
        "start": "gulp",
        "build": "gulp build --prod"
    },
    "author": "Huy Nguyen - Wolfactive",
    "license": "ISC",
    "devDependencies": {
        "@babel/core": "^7.10.2",
        "@babel/preset-env": "^7.10.2",
        "@babel/preset-react": "^7.12.13",
        "@babel/register": "^7.10.1",
        "@wordpress/blocks": "^7.0.5",
        "@wordpress/editor": "^9.25.9",
        "@wordpress/i18n": "^3.18.0",
        "autoprefixer": "^9.8.0",
        "babel-loader": "^8.1.0",
        "browser-sync": "^2.26.7",
        "del": "^5.1.0",
        "gulp": "^4.0.2",
        "gulp-clean-css": "^4.3.0",
        "gulp-if": "^3.0.0",
        "gulp-imagemin": "^7.1.0",
        "gulp-postcss": "^8.0.0",
        "gulp-prettier": "^3.0.0",
        "gulp-replace": "^1.0.0",
        "gulp-sass": "^4.1.0",
        "gulp-sourcemaps": "^2.6.5",
        "vinyl-named": "^1.1.0",
        "webpack-stream": "^5.2.1",
        "yargs": "^15.3.1",
        "react": "^16.8.6",
        "react-dom": "^16.8.6"
    },
    "dependencies": {},
    "browserslist": [
        "> .5% or last 2 versions"
    ]
}

Sau khi đã copy xong vào file package.json, các bạn chạy lệnh npm install trên terminal tại thư mục plugin. Tuy nhiên cài như vầy thì chưa xong đâu 😁😁😁

Tiếp theo các bạn tạo file .babelrc để cấu hình source của chúng ta có thể complie React Js thành JS ES5.

"presets": ["@babel/preset-env"]

Bây giờ mới tới file chính để complie code nè. Các bạn tạo file gulpfile.babel.js.

Import các module cần thiết để viết các task cho gulp.

import { src, dest, watch, series, parallel } from 'gulp'
import yargs from 'yargs'
import sass from 'gulp-sass'
import cleanCss from 'gulp-clean-css'
import gulpif from 'gulp-if'
import postcss from 'gulp-postcss'
import license from 'gulp-header-license'
import sourcemaps from 'gulp-sourcemaps'
import autoprefixer from 'autoprefixer'
import named from 'vinyl-named'
import imagemin from 'gulp-imagemin'
import del from 'del'
import webpack from 'webpack-stream'
import browserSync from 'browser-sync'

Hàm khai báo và tạo server

Kích hoạt browser-sync -> Tác dụng của browser-sync giúp các bạn khi lưu file trong lúc dev trình duyệt sẽ tự động reload hoặc stream trực tiếp qua browser.

const PRODUCTION = yargs.argv.prod // Khai báo môi trường
const server = browserSync.create()
export const serve = (done) => {
    server.init({
        proxy: 'http://wagutenberg.dev', // put your local website link here
    })
    done()
}

Hàm complie SCSS thành CSS

export const styles = () => {
    return src([
        'src/scss/main.scss',
        'src/scss/editor.scss',
        'src/scss/frontend.scss',
    ])
        .pipe(gulpif(!PRODUCTION, sourcemaps.init()))
        .pipe(sass().on('error', sass.logError))
        .pipe(gulpif(PRODUCTION, postcss([autoprefixer])))
        .pipe(gulpif(PRODUCTION, cleanCss({ compatibility: 'ie8' })))
        .pipe(gulpif(!PRODUCTION, sourcemaps.write()))
        .pipe(dest('dist/css'))
        .pipe(server.stream())
}

Trong hàm này nếu như ở môi trường develop, file css được complie sẽ được khi sourcemap để tiện cho việc sửa css, Ở đây mình có 3 file scss.

  • main.scss để chứa các css cần thiết để sửa theme hay sửa admin bên trong.
  • editor.scss chứa các css cần thiết cho phần khung editor trong phần editor Gutenberg.
  • frontend,scss để chứa các css cho các block Gutenberg ngoài giao diện (frontend)

Hàm complie từ React và ES6 sang ES5

export const scripts = () => {
    return src([
        'src/js/frontend/root.js',
        'src/js/gutenbergs/editor/editor.jsx',
        'src/js/gutenbergs/frontend/frontend.jsx',
    ])
        .pipe(named())
        .pipe(
            webpack({
                module: {
                    rules: [
                        {
                            test: /\.js$/,
                            use: {
                                loader: 'babel-loader',
                                options: {
                                    presets: ['@babel/preset-env'],
                                },
                            },
                        },
                        {
                            test: /\.jsx$/,
                            use: {
                                loader: 'babel-loader',
                                options: {
                                    presets: [
                                        '@babel/preset-env',
                                        [
                                            '@babel/preset-react',
                                            {
                                                pragma:
                                                    'wp.element.createElement',
                                                pragmaFrag:
                                                    'wp.element.Fragment',
                                                development: PRODUCTION
                                                    ? 'production'
                                                    : 'development',
                                            },
                                        ],
                                    ],
                                },
                            },
                        },
                    ],
                },
                plugins: [new VueLoaderPlugin()],
                resolve: {
                    extensions: ['*', '.js', '.json', '.jsx'],
                },
                mode: PRODUCTION ? 'production' : 'development',
                devtool: !PRODUCTION ? 'inline-source-map' : false,
                externals: {
                    '@wordpress/blocks': ['wp', 'blocks'],
                    '@wordpress/i18n': ['wp', 'i18n'],
                    '@wordpress/editor': ['wp', 'editor'],
                    '@wordpress/components': ['wp', 'components'],
                },
                output: {
                    filename: '[name].js',
                },
            })
        )
        .pipe(dest('dist/js'))
}

Hàm trên cũng như hàm complie từ scss sang css. Có 3 file tương ứng cho 3 mục đích trên. Đồng thời mình khai báo external cho 4 package @wordpress/blocks, @wordpress/i18n, @wordpress/editor, @wordpress/components, vì các package này đã cấu hình sẵn trong WordPress và chúng ta không cần tích hợp vào file js để giảm kích thước js sau khi complie xong. Mình dùng npm cài vào các package trên chủ yếu để IDE có thể truy suất và gợi ý các property, method, function, param có liên quan trong các package đó.

Hàm copy ảnh và nén ảnh

export const images = () => {
    return src(
        '/src/images/**/*.{jpg,jpeg,png,svg,gif}'
    )
        .pipe(gulpif(PRODUCTION, imagemin()))
        .pipe(dest('dist/images'))
}

Hàm copy các file cần thiết trong thư mục src

export const copy = () => {
    return src([
        'src/**/*',
        '!src/{images,js,scss}',
        '!src/{images,js,scss}/**/*',
    ]).pipe(dest('dist'))
}

Các hàm cần thiết khác

export const reload = (done) => {
    server.reload()
    done()
}

export const watchForChanges = () => {
    watch('src/scss/**/*.scss', styles)
    watch('src/images/**/*.{jpg,jpeg,png,svg,gif}', series(images, reload))
    watch(
        ['src/**/*', '!src/{images,js,scss}', '!src/{images,js,scss}/**/*'],
        series(copy, reload)
    )
    watch(['src/js/**/*.js', 'src/js/**/*.jsx'], series(scripts, reload))
    watch('**/*.php', reload)
}

export const clean = () => del(['dist/js', 'dist/css/main.scss', 'dist/images'])

Khai báo task với gulp

export const dev = series(
    clean,
    parallel(styles, images, copy, scripts),
    serve,
    watchForChanges
)
export const build = series(clean, parallel(styles, images, copy, scripts), pot)
export default dev

Vậy là để chạy được bộ source này các bạn chỉ cần chạy các lệnh

  • npm run start -> Chạy môi trường develop
  • npm run buld -> Build code để đưa code lên server
  • Cấu trúc thư mục js và scss các bạn có thể tham khảo ở ảnh này
    plugin-ho-tro-viet-block-gutenberg

    Tổng kết

    Sau khi làm xong file gulpfile.babel.js. Chúng ta khai báo css và js cho WordPress. Mình sẽ hướng dẫn các bạn trong bài kế tiếp Tạo Block Gutenberg đầu tiên
    Các bạn có thể tham khảo tổng quan về series tại đây
    Cảm ơn các bạn đã đón đọc. Các bạn có thắc mắc hay có vấn đề cần giải đáp thì hay inbox vào fanpage Wolfactive nhé.

Vui lòng chọn size trước khi đặt hàng (*)