Pengembangan portal frontend pada perangkat lunak open source: berbagi pengalaman

Di bagian pertama artikel tentang cara kami membuat solusi portal untuk pengusaha terbesar di Rusia, arsitekturnya dijelaskan oleh backend. Dalam artikel ini kita akan meneruskan ke frontend.



Seperti yang sudah disebutkan di bagian pertama, tujuan utama kami adalah mengembangkan platform yang dapat dengan mudah ditingkatkan dan dipelihara.

Reuseability Bagian

depan sebagian besar ditulis dalam Vue.js, dan karena seluruh portal dibagi menjadi portlet, masing-masing dari mereka adalah contoh Vue yang terpisah dengan Vuex, Vue Router dan komponennya sendiri. Setiap instance seperti itu dipindahkan ke repositori sendiri.

Karena portlet ada di dalam repositori, muncul pertanyaan tentang bagaimana tidak menulis banyak jenis kode yang sama untuk portlet yang berbeda. Untuk mengatasi masalah ini, kami mentransfer semua yang dapat digunakan kembali ke repositori terpisah, yang kemudian dihubungkan melalui .gitmodules. Saat ini ada dua submodul seperti itu.

Satu menyimpan fungsionalitas umum: ini adalah komponen umum, layanan, konstanta, dll. Kami memiliki modul ini yang disebut Vue-common.

Submodule kedua berisi pengaturan untuk perakitan, itu menyimpan konfigurasi untuk paket web, serta loader dan pembantu yang diperlukan selama perakitan. Modul ini disebut Vue-bundler.

Untuk kenyamanan bekerja dengan API, metode REST juga dibagi menjadi umum dan lokal. Dalam Vue-common, metode diperkenalkan untuk mendapatkan daftar pengguna portal, metode administrasi, akses ke sistem file portal, dan lainnya. Semua titik akhir API dipindahkan ke layanan terpisah yang terdaftar di titik masuk dan terhubung ke instance Vue. Kemudian mereka dapat digunakan di mana saja dalam aplikasi.

Setiap layanan individual terdaftar di dalam plugin. Vue memiliki fungsi penggunaan bawaan untuk menghubungkan plugin. Baca lebih lanjut tentang plugin di Vue di sini .

Plugin itu sendiri diinisialisasi seperti ini:

class Api {
    constructor () {
        //  http ,   
        this.instance = instance

        //     
       //     this,      http 
        Object.keys(commonServices).forEach(name => commonServices[name](this))
        
        //     
	requireService.keys().forEach(filename => requireService(filename).default(this))
    }

    install () {
	Vue.prototype.$api= this
    }
}

export default new Api()

Selain inisialisasi:

  1. Contoh klien http dibuat. Yang menentukan baseURL dari backend dan header kita

    const instance = axios.create({
    	baseURL: '/example/api',
    	responseType: 'json',
    	headers: {
    		'Content-Type': 'application/json',
    		'Cache-Control': 'no-cache',
    		'Pragma': 'no-cache',
    	}
    })
                    backend   ,   axios.

  2. Layanan dibuat yang menyimpan permintaan itu sendiri

    // api -   http 
    export default api => {
    	api.exampleService= {
    		exampleGetRequest(params) {
    			return api.instance.request({
    				method: 'get',
    				url: `example/get`,
    				params
    			})
    		},
    		examplePostRequest(data) {
    			return api.instance.request({
    				method: 'post',
    				url: `example/post`,
    				data
    			})
    		},
    	}
    }
    

    Dalam vue-common cukup untuk membuat hanya layanan seperti itu, dan sudah terdaftar untuk setiap portlet di kelas Api
  3. Layanan umum dan lokal terdaftar

         const requireService = require.context('./service', false, /.service.js$/)
    

Dalam komponen, mereka digunakan sangat sederhana. Contohnya:

export default {
	methods: {
		someMethod() {
    			this.$api.exampleService.exampleGetRequest()
}
}
}

Jika Anda perlu membuat permintaan di luar aplikasi, Anda dapat melakukan ini:

//    (@ -     )
import api from ‘@/api’

//        
api.exampleService.exampleGetRequest()

Penskalaan

Seperti disebutkan di atas, satu bundel terpisah dikumpulkan untuk setiap portal, dan setiap bundel memiliki titik masuknya sendiri. Di masing-masing komponen, komponen dan aset terdaftar, otorisasi dikonfigurasikan untuk pengembangan lokal, dan plug-in terhubung.

Komponen terdaftar secara global untuk setiap aplikasi, baik lokal maupun umum.

Registrasi komponen terlihat seperti ini:

import _ from “lodash”

const requireComponent = require.context('@/components', true, /^[^_].+\.vue$/i)

requireComponent.keys().forEach(filename => {
    const componentConfig = requireComponent(filename)

    // Get PascalCase name of component
    const componentName = _.upperFirst(
        _.camelCase(/\/\w+\.vue/.exec(filename)[0].replace(/^\.\//, '').replace(/\.\w+$/, ''))
    )

    Vue.component(componentName, componentConfig.default || componentConfig)
})

Terkadang menjadi penting untuk portal yang kami kembangkan untuk menambahkan fungsionalitas yang unik, dan untuk ini Anda harus menulis komponen yang unik untuknya, atau hanya mengimplementasikan komponen dengan cara yang berbeda. Sudah cukup untuk membuat komponen dalam folder terpisah, misalnya / components-portal / * nama portal * / *. Vue, dan mendaftarkannya di titik entri yang diinginkan, menambahkan memerlukan. Konteks bukan untuk satu folder, tetapi untuk beberapa.

const contexts = [
    require.context('@/components', true, /^[^_].+\.vue$/i),
   require.context('@/components-portal/example', true, /^[^_].+\.vue$/i)
]

contexts.forEach(requireComponent => {
    requireComponent.keys().forEach(filename => {
        const componentConfig = requireComponent(filename)

        // Get PascalCase name of component
        const componentName = _.upperFirst(
            _.camelCase(/\/\w+\.vue/.exec(filename)[0].replace(/^\.\//, '').replace(/\.\w+$/, ''))
        )

        Vue.component(componentName, componentConfig.default || componentConfig)
    })
})

Jika Anda menetapkan nama yang sama untuk komponen untuk portal tertentu seperti dari perpustakaan umum komponen, maka itu hanya akan ditulis ulang sebagai properti objek dan akan digunakan sebagai komponen untuk portal ini.

Aset seperti ikon svg juga terdaftar secara global. Kami menggunakan svg-sprite-loader untuk membuat sprite dari ikon svg dan kemudian menggunakannya melalui <use: xlink: href = "# * icon name *" />

Mereka terdaftar seperti ini:

const requireAll = (r) => r.keys().forEach(r)

const requireContext = require.context('@/assets/icons/', true, /\.svg$/)

requireAll(requireContext)

Untuk mengukur tidak hanya fungsionalitas, tetapi juga gaya komponen, kami telah menerapkan mekanisme untuk mengubah gaya untuk portal tertentu. Komponen file tunggal menentukan gaya dalam tag <style> dan digunakan secara default. Untuk menerapkan gaya untuk portal tertentu, Anda harus mendaftarkannya di tag lain

All Articles