欧美三级国产三级日韩三级_亚洲熟妇丰满大屁股熟妇_欧美亚洲成人一区二区三区_国产精品久久久久久模特

Medusa 微信小程序工程化實踐方案 - 新聞資訊 - 云南小程序開發(fā)|云南軟件開發(fā)|云南網(wǎng)站建設(shè)-昆明葵宇信息科技有限公司

159-8711-8523

云南網(wǎng)建設(shè)/小程序開發(fā)/軟件開發(fā)

知識

不管是網(wǎng)站,軟件還是小程序,都要直接或間接能為您產(chǎn)生價值,我們在追求其視覺表現(xiàn)的同時,更側(cè)重于功能的便捷,營銷的便利,運營的高效,讓網(wǎng)站成為營銷工具,讓軟件能切實提升企業(yè)內(nèi)部管理水平和效率。優(yōu)秀的程序為后期升級提供便捷的支持!

您當(dāng)前位置>首頁 » 新聞資訊 » 小程序相關(guān) >

Medusa 微信小程序工程化實踐方案

發(fā)表時間:2021-1-5

發(fā)布人:葵宇科技

瀏覽次數(shù):71

4月份的時候我曾發(fā)布過《微信小程序工程化探索之webpack實戰(zhàn)》一文,當(dāng)時是我探索微信小程序工程化的第一階段。起初我只是為了驗證微信小程序與 webpack 是否能夠相結(jié)合(很大程度是被對于技術(shù)的好奇心驅(qū)使),對于工程化的持續(xù)交付并沒有過多的思考。但是在內(nèi)部需求的不斷沖擊下,我開始萌生以工程化手段持續(xù)簡化微信小程序開發(fā)難度的想法,最終衍生的產(chǎn)物就是這套以 Medusa 命名的微信小程序快速開發(fā)方案。

接下來我將較為詳細的分享達成這一方案的實踐過程,下文中將提到的工具我也已經(jīng)發(fā)布在 npm 上供大家下載使用。這篇文章將會覆蓋之前發(fā)表的那篇文章的全部內(nèi)容并且內(nèi)容更加豐富,所以篇幅方面也較為長請讀者們耐心閱讀。

webpack-build-miniprogram

webpack-build-miniprogram 是 Medusa 方案的基礎(chǔ)也是核心,這一工具包提供了以 webpack 構(gòu)建微信小程序的能力,并且我們可以利用 webpack 的生態(tài)持續(xù)豐富 Medusa 的功能。在講述基礎(chǔ)構(gòu)建配置之前,我們先來看看 Medusa 的目錄結(jié)構(gòu)基礎(chǔ),有了相應(yīng)的目錄約束才使得項目更加規(guī)范化。

|-- dist                        編譯結(jié)果目錄
|-- src                         源代碼目錄
|   |-- app.js                  項目入口文件
|   |-- app.json                小程序配置文件
|   |-- sitemap.json            sitemap配置文件
|   |-- assets                  靜態(tài)資源存放目錄
|   |   |-- .gitkeep
|   |-- components              公共組件存放目錄
|   |   |-- .gitkeep
|   |-- dicts                   公共字典存放目錄
|   |   |-- .gitkeep
|   |-- libs                    第三方工具庫存放目錄(外部引入)
|   |   |-- .gitkeep
|   |-- pages                   頁面文件存放目錄
|   |   |-- index
|   |       |-- index.js
|   |       |-- index.json
|   |       |-- index.less
|   |       |-- index.wxml
|   |-- scripts                 公共腳本存放目錄(wxs)
|   |   |-- .gitkeep
|   |-- services                API服務(wù)存放目錄
|   |   |-- .gitkeep
|   |-- styles
|   |   |-- index.less          項目總通用樣式
|   |   |-- theme.less          項目主題樣式
|   |-- templates               公共模板存放目錄
|   |   |-- .gitkeep
|   |-- utils                   公共封裝函數(shù)存放目錄(自我封裝)
|       |-- .gitkeep
|-- .env                        環(huán)境變量配置文件
|-- config.yaml                 編譯配置文件
|-- webpack.config.js           webpack 配置擴展文件
|-- project.config.json         開發(fā)者工具配置文件
└── package.json
復(fù)制代碼

基礎(chǔ)篇

webpack 這一工具現(xiàn)在已經(jīng)成為前端工程師的必備技能,復(fù)雜的工作原理讓我們對它總是有種敬畏感,所以在做微信小程序構(gòu)建策略過程中,我們先將它簡單的理解為一個“搬運工具”。它將源代碼目錄中的文件加以某些處理之后再輸出到目標(biāo)目錄中?,F(xiàn)在我們明確一下我們要搬運哪些文件,微信小程序中涉及到的主要有:

  • 邏輯文件 .js 
  • 配置文件 .json 
  • 模板文件 .wxml 
  • 樣式文件 .wxss .less .scss 
  • 腳本文件 .wxs 
  • 靜態(tài)資源文件 assets/ 

基礎(chǔ)搬運功能

接下來我們將書寫 webpack 的公共部分配置,利用 copy-webpack-plugin 這一插件來完成大部分文件的搬運工作。

/** config/webpack.common.js */
const CopyPlugin = require("copy-webpack-plugin");

const config = {
  context: SOURCE,
  devtool: 'none',
  entry: {
        app: './app.js'
  },
  output: {
    filename: '[name].js',
    path: DESTINATION
  },
  plugins: [
    new CopyPlugin([
      {
        from: 'assets/',
        to: 'assets/',
        toType: 'dir'
      },
      {
        from: '**/*.wxml',
        toType: 'dir'
      },
      {
        from: '**/*.wxss',
        toType: 'dir'
      },
      {
        from: '**/*.json',
        toType: 'dir'
      },
      {
        from: '**/*.wxs',
        toType: 'dir'
      }
    ])
  ]
};
復(fù)制代碼

以上簡單的配置我們就實現(xiàn)了除邏輯文件與預(yù)編譯語言文件以外的搬運工作,在配置中出現(xiàn)了 SOURCE 、 DESTINATION 兩個常量,它們分別代表的是源代碼目錄與目標(biāo)代碼目錄的絕對路徑,我們將它們抽離在單獨的字典文件中:

/** libs/dicts.js */
const path = require("path");

exports.ROOT = process.cwd();
exports.SOURCE = path.resolve(this.ROOT, 'src');
exports.DESTINATION = path.resolve(this.ROOT, 'dist');
exports.NODE_ENV = process.argv.splice(2, 1)[0];
復(fù)制代碼

上面搬運的文件因為不需要特殊的內(nèi)容處理,所以完全交由插件去實現(xiàn),剩余兩種類型的文件我們就需要使用到 webpack 的入口(entry)、插件(plugin)loader 協(xié)同合作才能完成搬運工作。

核心入口功能

首先我們要解決如何生成入口的問題,解決了入口生成的問題才能借助 loader 去完成文件內(nèi)容的轉(zhuǎn)化。對于入口生成這一問題,我開發(fā)了另外一個插件 entry-extract-webpack-plugin 去解決。這一插件我并不打算詳細的講解實現(xiàn)的過程,我只會闡述它的核心實現(xiàn)思路(如果你有興趣進一步了解可以下載下來直接看源碼)。

微信小程序需要建立入口網(wǎng)絡(luò)其實是有規(guī)律可循的,主包、分包都會配置在 app.json 文件中,頁面所需要的組件也會配置在 [page].json 文件中。抓住這一特點,我們可以將實現(xiàn)插件功能的核心羅列為以下幾點:

  • 通過 node.js  提供的 path  與 fs  模塊功能,以 app.json 文件中配置的路徑為基礎(chǔ),遞歸的去尋找每個 page 所依賴的 component 路徑,最終整合在同個數(shù)組中。
  • 利用 webpack 提供的 SingleEntryPlugin 和 MultiEntryPlugin 插件,在 entryOption 生命周期鉤子中將第一步收集的路徑數(shù)組注入到構(gòu)建當(dāng)中形成入口(entry)。
  • 構(gòu)建監(jiān)聽的過程中如果有新的頁面添加,則通過 watchRun 生命周期將新的入口加入到之前的入口(entry)中。

以上三點是實現(xiàn)生成入口這一功能的核心思路,除了核心的實現(xiàn)思路外,我還想簡單的講解下我們?nèi)绾稳懸粋€ webpack 插件:

class EntryExtractPlugin {
  constructor(options) {}
  
  apply(compiler) {
    compiler.hooks.entryOption.tap('EntryExtractPlugin', () => {
        ...
    });
    compiler.hooks.watchRun.tap('EntryExtractPlugin', () => {
        ...
    });
  }
}
復(fù)制代碼

webpack 的插件大致是以的形式存在,當(dāng)你使用插件時,它會自動執(zhí)行 apply 方法, 然后使用 compiler.hooks 對象上的各種生命周期屬性便可以將我們需要的處理邏輯植入到 webpack 的構(gòu)建流程當(dāng)中。

邏輯與樣式

上面解決了生成入口(entry)的問題,接下來我們在原有的基礎(chǔ)上完善一下策略。由于預(yù)編譯語言的類型較多,我為了策略的可擴展性將樣式部分的策略抽離為單獨的部件,然后在通過 webpack-merge 這一工具將它們合并起來,完整的實現(xiàn)如下:

/** config/webpack.parts.js */
exports.loadCSS = ({ reg = /\.css$/, include, exclude, use = [] }) => ({
    module: {
    rules: [
      {
        include,
        exclude,
        test: reg,
        use: [
          {
            loader: require('mini-css-extract-plugin').loader
          },
          {
            loader: 'css-loader'
          }
        ].concat(use)
      }
    ]
  }
});
復(fù)制代碼
/** config/webpack.common.js */
const { merge } = require('webpack-merge');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const parts = require('./webpack.parts.js');

const config = {
  ...
  module: {
    rules: [
      {
        test: /\.js$/,
        loader: 'babel-loader',
        exclude: /node_modules/
      }
    ]
  },
  plugins: [
    ...
    new MiniCssExtractPlugin({ filename: '[name].wxss' })
  ]
};

module.export = merge([
    config,
  parts.loadCSS({
    reg: /\.less$/,
    use: ['less-loader']
  })
]);
復(fù)制代碼

以上就是基礎(chǔ)的 webpack 策略,接下來我們書寫一個工具包的可執(zhí)行文件便可以在項目當(dāng)中通過 medusa-server {mode} 使用 webpack 提供的功能了。我們需要在工具包的 package.json 文件中配置 bin 字段,它標(biāo)志了我們通過命令會自動執(zhí)行哪個文件。

{
  ...
  main: "index.js",
  bin: {
    "medusa-server": "index.js"
  }
}
復(fù)制代碼
/** index.js */
const webpack = require('webpack');
const { merge } = require('webpack-merge');
const chalk = require('chalk');
const commonConfig = require('./config/webpack.common');
const { NODE_ENV } = require('./libs/dicts');

const config = (function(mode) {
  if (mode === 'production') {
    return merge([commonConfig, { mode }]);
  }
  return merge([commonConfig, {
    mode: 'development',
    watch: true,
    watchOptions: { ignored: /node_modules/ }
  }])
})(NODE_ENV);

webpack(config, (err, stats) => {
  if (err) {
    console.log(chalk.red(err.stack || err));
    if (err.details) {
        console.log(chalk.red(err.details));
    }
    return undefined;
  }
  const info = stats.toJson();
  if (stats.hasErrors()) {
    console.log(chalk.red(info.errors));
  }
  if (stats.hasWarnings()) {
    console.log(chalk.yellow(info.warnings));
  }
});
復(fù)制代碼

進階篇

基礎(chǔ)篇當(dāng)中完成的 webpack 配置已經(jīng)可以滿足兩點功能,一是對常規(guī)文件的輸出,二是具備開發(fā)與生產(chǎn)兩種不同的模式。對于基礎(chǔ)篇我還有兩點要說明一下:

為什么沒有應(yīng)用ES6(更改版本)轉(zhuǎn)為ES5的相關(guān)插件?


因為在實踐當(dāng)中發(fā)現(xiàn)IOS的10.x版本存在async/await語法無法正常使用的情況,所以索性就讓構(gòu)建更加純粹一些 ,然后啟用微信開發(fā)者工具的 ES6 轉(zhuǎn) ES5增強編譯 這兩項功能,由官方工具去處理新特性。

為什么 devtool 要設(shè)置為 none,難道不需要 sourceMap 嗎?


微信官方已經(jīng)原生提供了SourceMap功能,這在你上傳版本時開發(fā)者工具中就已經(jīng)有體現(xiàn)了。

接下來就進入進階篇的梳理,在滿足正常的輸出后其實與原生開發(fā)好像并沒有太大差異,這完全體現(xiàn)不出 webpack 的作用,所以我們要利用 webpack 的能力及其相關(guān)的工具生態(tài)來擴展下 Medusa 的功能。接下來我們將賦予 Medusa 以下幾點功能:

  • 路徑別名 @
  • 根據(jù)環(huán)境自動注入相應(yīng)的環(huán)境域名
  • ESLint、StyleLint代碼規(guī)范檢查
  • 路由功能
  • 公共代碼抽取
  • 環(huán)境變量
  • webpack 可擴展

路徑別名 @

原生微信小程序只支持相對路徑的引入方式,但是我們難免會遇到必須移動某些文件的情況,假設(shè)這個文件在多處被引用,那就頭疼了。所以我們通過 webpack 的能力以及搭配 jsconfig.json 配置文件可以讓我們有更好的開發(fā)體驗。

/** config/webpack.common.js */
const config = {
  ...
  resolve: {
    alias: {
        '@': SOURCE
    }
  }
};
復(fù)制代碼
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"],
    },
    "target": "ES6",
    "module": "commonjs",
    "allowSyntheticDefaultImports": true,
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules"],
}
復(fù)制代碼

通過 alias 別名配置,@ 符號就可以指代 src 源代碼目錄,然后在實際業(yè)務(wù)項目的根目錄下創(chuàng)建一個 jsconfig.json 文件,通過以上的配置在使用 vscode 編輯器時就可以獲得良好的智能路徑提示功能。

自動注入相應(yīng)的環(huán)境域名

在介紹這個功能之前,我需要先講解一下 config.yaml 這個配置文件的作用。這是我一開始設(shè)想用來擴展各種功能的配置文件,它應(yīng)用在實際業(yè)務(wù)項目的根目錄中。現(xiàn)階段它的功能還相當(dāng)少,不過將來應(yīng)該會逐步迭代增加的。

# 當(dāng)前項目應(yīng)用平臺
platform: wx
# 樣式單位 px 轉(zhuǎn)換 rpx 的比例設(shè)定
css_unit_ratio: 1
# 域名配置
development_host:
  api: https://www.miniprogram.dev.com
production_host:
  api: https://www.miniprogram.pro.com
復(fù)制代碼

這其中的域名配置是可以自由增減的,書寫形式形如例子當(dāng)中所示。當(dāng)我們在其中配置好對應(yīng)環(huán)境的域名后,我們在業(yè)務(wù)代碼當(dāng)中便可以用 mc.$hosts.api 變量輕松的訪問域名。在構(gòu)建過程中工具會自動幫你將對應(yīng)環(huán)境的域名注入代碼當(dāng)中,你再也不用關(guān)心如何去管理和切換不同環(huán)境域名的問題了。下面展示一下我是如何實現(xiàn)這一功能的:

/** libs/dicts */
exports.CONFIG = path.resolve(this.ROOT, 'config.yaml');
exports.DEFAULT_CONFIG = {
  platform: 'wx',
  css_unit_ratio: 1,
};
復(fù)制代碼
/** libs/index.js */
const fs = require('fs');
const yaml = require('js-yaml');
const { CONFIG, DEFAULT_CONFIG } = require('./dicts');

exports.yamlConfig = (function() {
  try {
    /** 將 yaml 格式的內(nèi)容解析為 object 對象 */
    const config = yaml.load(fs.readFileSync(CONFIG, { encoding: 'utf-8' }));
    return config;
  } catch(e) {
    return DEFAULT_CONFIG;
  }
})();
復(fù)制代碼
/** webpack.common.js */
const webpack = require('webpack');
const { yamlConfig } = require('../libs');
const { NODE_ENV } = require('../libs/dicts');

const config = {
  ...
  plugins: [
    ...
    new webpack.DefinePlugin({
        mc: JSON.stringify({
        $hosts: yamlConfig[`${NODE_ENV}_host`] || {}
      })
    })
  ]
};
復(fù)制代碼

webpack.DefinePlugin 插件可以判別代碼中 mc 這個標(biāo)識符然后進行相應(yīng)的替換功能,這樣就能保證代碼的正常運作。

ESLint 與 StyleLint

編碼規(guī)范已經(jīng)是老生常談的話題了,今年我所處的前端團隊擴容到二十幾人,在多人共同協(xié)作和不同成員維護的情況下,我們迫切的需要統(tǒng)一的編碼規(guī)范來減少維護的成本。(在規(guī)范落地上,我還有兩句題外話要說,當(dāng)我們需要落地一項規(guī)范的時候,不要停留在討論規(guī)則上,也不要妄想用人的自律去約束編碼。如果你的團隊也需要實施這些東西,希望你能夠成為先驅(qū)者將規(guī)則先定下初版,然后找一個合適的工具,通過工具去約束人的行為。)接下來我們就來看下我們所需要的檢查工具是如何配置的:

/** webpack.common.js */
const StylelintPlugin = require('stylelint-webpack-plugin');

const config = {
  module: {
    rules: [
      {
        enforce: 'pre',
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'eslint-loader',
        options: {
            fix: true,
          cache: false,
          formatter: require('eslint-friendly-formatter')
        }
      }
    ]
  },
  plugins: [
    new StylelintPlugin({
        fix: true,
      files: '**/*.(sa|sc|le|wx|c)ss'
    })
  ]
};
復(fù)制代碼

以上配置的兩個工具可以對 js 與樣式文件按照一定的規(guī)則集進行檢查,對于部分不符合規(guī)范的代碼可以自行修復(fù),無法自動修復(fù)的部分將會給出相應(yīng)的提示。應(yīng)用什么規(guī)則集你可以通過業(yè)務(wù)項目根目錄中的 .eslintrc 和 .stylelintrc 文件去決定(下面的章節(jié)我會對規(guī)范這一塊再進行相應(yīng)的展開)。

公共代碼抽取

在應(yīng)用 webpack 之后,我們?yōu)槲⑿判〕绦蜷_發(fā)賦予了 npm 加載依賴的能力。在模塊化打包的機制下,工具包會被加載進引用它的入口當(dāng)中,這會導(dǎo)致微信小程序包大小及其容易就超出限定值了,所以我們的解決方案是將多次出現(xiàn)的代碼抽離為單獨的公共部分,具體的實施代碼如下:

/** config/webpack.common.js */
const config = {
  ...
  output: {
    ...,
    globalObject: 'global'
  },
  plugins: [
    ...
    new webpack.BannerPlugin({
        raw: true,
      include: 'app.js',
      banner: 'const vendors = require("./vendors");\nconst commons = require("./commons");\nconst manifest = require("./manifest");'
    })
  ],
  optimization: {
    cacheGroups: {
        vendors: {
        chunks: 'initial',
        name: 'vendors',
        test: /[\\/]node_modules[\\/]/,
        minChunks: 3,
        priority: 20
      },
      commons: {
        chunks: 'initial',
        name: 'commons',
        test: /[\\/](utils|libs|services|apis|models|actions|layouts)[\\/]/,
        minChunks: 3,
        priority: 10
      }
    },
    runtimeChunk: {
        name: 'manifest'
    }
  }
};
復(fù)制代碼

微信小程序的全局變量可以通過 global 訪問,所以我們需要將 output.globalObject  屬性設(shè)置為 global。webpack 內(nèi)置的 BannerPlugin 插件可以將我們需要的語句插入在指定的文件的頭部,利用它我們就做到了將抽離出來的公共文件重新引入到依賴網(wǎng)格中。

環(huán)境變量

我們在使用 Vue 、React 的腳手架創(chuàng)建的項目時會見到 .env 這個文件,它的主要作用是擴展開發(fā)者所需的環(huán)境變量。在微信小程序擴展環(huán)境變量變量這樣的需求可能少之又少,但是我們可以換一種思路,我們可以利用它來擴展開發(fā)者所需的全局變量。接下來我們將利用 dotenv-webpack 這一工具來實現(xiàn)這個功能,它可以讀取業(yè)務(wù)項目根目錄下的 .env 文件內(nèi)容,使得我們在編碼中也可以使用當(dāng)中的變量值。

/** config/webpack.common.js */
const Dotenv = require('dotenv-webpack');
const { ENV_CONFIG } = require('../libs/dicts');

const config = {
  ...
  plugins: [
    ...
    new Dotenv({ path: ENV_CONFIG })
  ]
};
復(fù)制代碼

webpack 擴展

通過 webpack 我已經(jīng)實現(xiàn)了通用的許多功能,但是我所處的公司開發(fā)的微信小程序頗多,所以難免有一些項目需要個性化的定制策略。既然有這樣的需求,我們就應(yīng)該提供這樣的能力給到業(yè)務(wù)開發(fā)者,一來我們可以從多個項目當(dāng)中吸收更多需要集成的功能點,二來可以暫時減輕自身的負(fù)擔(dān)。webpack-merge 這一工具其實在前面樣式部分合并我已經(jīng)使用過了,我們只需要提供業(yè)務(wù)項目 webpack 配置的路徑即可,再修改下之前的執(zhí)行文件。

/** index.js */
const { WEBPACK_CONFIG } = require('./libs/dicts');

const config = (function(mode) {
  if (mode === 'production') {
    return merge([commonConfig, { mode }, WEBPACK_CONFIG]);
  }
  return merge([commonConfig, {
    mode: 'development',
    watch: true,
    watchOptions: { ignored: /node_modules/ }
  }, WEBPACK_CONFIG])
})(NODE_ENV);

...
復(fù)制代碼

路由功能

微信官方提供了關(guān)于路由跳轉(zhuǎn)的 API ,但我認(rèn)為官方的 API 在日常開發(fā)中有幾點不便:

  1. 需要輸入完整的路徑字符串,路徑太長難以記憶不說,假如頁面路徑有所修改需要投入較高的維護成本。
  2. 跳轉(zhuǎn)方式多樣,四種不同類型的跳轉(zhuǎn) API 較為常用的是 navigateTo,因為 API 有多個并且參數(shù)也較多,所以使用時難免都省不了再去查閱一遍文檔。
  3. 官方提供的任何一種 API 最終目標(biāo)頁面中接收到的 query 都是字符串類型,這一定程度上限制了我們的編碼設(shè)計。

為了解決上述的三個問題,我將 API 進行了二次封裝,從中抹除四種跳轉(zhuǎn)類型的差異,通過統(tǒng)一的接口就可以達到四種跳轉(zhuǎn)方法的效果。并且通過 webpack 的全局變量注入功能優(yōu)化了路徑字符串的獲取,方便使用并且容易維護。

mc.$routes
我將頁面的文件夾名稱與路徑相關(guān)聯(lián),兩者形成映射關(guān)系的話,我們只需要書寫文件夾名稱便可。原來我們需要使用 pages/home/index 訪問 home 頁面,通過我的改造之后,我們可以通過 mc.$routes.home 訪問 home 頁面。

medusa-wx-router
medusa-wx-router 是我對路由功能進行二次封裝后的工具包,具體的實現(xiàn)過程在這里我就不詳述了,你可以自行下載使用或是依照你的需求進行再次改造,下面我只展示一下在業(yè)務(wù)代碼中結(jié)合 mc.$routes 如何使用:

mc.routerTo({
  url: mc.$routes.home,
  type: 'push',
  query: {
    id: 0,
    bool: true
  },
  success: () => console.log('successfully')
});
/** push 方式快捷形式 */
mc.routerTo(mc.$routes.home, { id: 0, bool: true });
復(fù)制代碼

為了省去 import 路由工具包這一步驟,我使用了 webpack.ProvidePlugin 這一插件自動幫我們在有使用的地方補充 import 功能。

/** config/webpack.common.js */
const config = {
  ...
  plugins: [
    ...
    new webpack.ProvidePlugin({
      'mc.routerTo': ['medusa-wx-router', 'routerTo'],
      'mc.decoding': ['medusa-wx-router', 'decoding'],
      'mc.back': ['medusa-wx-router', 'back'],
      'mc.goHome': ['medusa-wx-router', 'goHome'],
    })
  ]
};
復(fù)制代碼

規(guī)范

規(guī)范是工程的重要一環(huán),一個團隊必須遵照同一套規(guī)則進行編碼,規(guī)范的存在使得代碼的質(zhì)量得以提升,有統(tǒng)一的規(guī)范認(rèn)知使得成員互相交接項目更加輕松高效。

規(guī)則集其實就是一個包含規(guī)則的配置文件,接下來我會給出具體的配置內(nèi)容。當(dāng)然在考慮到規(guī)則集的團隊定制性和升級的問題,我將 ESLint 和 StyleLint 的規(guī)則都制作成了 npm 包,這就解決了所有業(yè)務(wù)項目統(tǒng)一規(guī)則的問題。對應(yīng)的 npm 包分別是 eslint-config-medusa 和 stylelint-config-medusa ,這是我所處的團隊所需要的,所以對于你們在實踐時可以結(jié)合你們團隊的現(xiàn)有情況進行改造。

# EditorConfig is awesome: https://EditorConfig.org

# top-most EditorConfig file
root = true

[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true

[*.md]
trim_trailing_whitespace = false
復(fù)制代碼

在業(yè)務(wù)項目的根目錄中創(chuàng)建 .editorconfig 文件配合 vscode 的 EditorConfig for VS Code 插件便可以對常規(guī)的文件進行基礎(chǔ)的編碼約束。

module.exports = {
  parserOptions: {
    ecmaVersion: "2018",
    sourceType: "module"
  },
  parser: "babel-eslint",
  env: {
    node: true,
    commonjs: true,
    es6: true
  },
  globals: {
    mc: false,
    wx: true,
    swan: true,
    App: true,
    Page: true,
    Component: true,
    Behavior: true,
    getApp: true,
    getCurrentPages: true
  },
  extends: ["airbnb-base"],
  rules: {
    // disallow use of console
    "no-console": "warn",

    // disallow use of debugger
    "no-debugger": "error",

    // disallow dangling underscores in identifiers
    'no-underscore-dangle': 'off',

    // specify the maximum length of a line in your program
    "max-len": ["error", 120],

    // require return statements to either always or never specify values
    "consistent-return": ["error", { "treatUndefinedAsUnspecified": true }],

    // disallow usage of expressions in statement position
    "no-unused-expressions": "off"
  },
  settings: {
    "import/resolver": {
      alias: {
        map: [
          ["@", "./src"],
          ["utils", "./src/utils"],
          ["services", "./src/services"]
        ],
        extensions: [".js", ".json", ".less"]
      }
    }
  }
};
復(fù)制代碼
module.exports = {
  rules: {
    // Disallow unknown type selectors
    'selector-type-no-unknown': null,

    // Disallow unknown units
    'unit-no-unknown': null
  },
  extends: [
    'stylelint-config-standard',
    'stylelint-config-recess-order'
  ],
  plugins: ['stylelint-order']
};
復(fù)制代碼

上面展示的就是我所完成的兩個規(guī)則集依賴包的入口文件,當(dāng)我們 install 依賴包之后,我們就可以在業(yè)務(wù)項目的 .eslintrc 和 .stylelintrc 文件中通過 extends 字段將它們引入。搭配 vscode 編輯器的 ESLint 和 stylelint-plus 插件,它們可以在編碼過程中就提醒你相應(yīng)的錯誤規(guī)則。

腳手架

前面說的構(gòu)建與規(guī)范全都是服務(wù)于具體的業(yè)務(wù)項目的,在擁有了基礎(chǔ)的能力之后,我們就該思考如何使得業(yè)務(wù)開發(fā)人員能夠快速并且符合要求的進行業(yè)務(wù)系統(tǒng)開發(fā)。讓他們不再需要考慮目錄應(yīng)該怎么約定,工具如何集成,編碼規(guī)范究竟如何應(yīng)用諸如這些問題。為了達成快速開發(fā)這一要求,我著手制作具備初始化項目這一簡易功能的腳手架。最終我將這一工具分為兩個項目,其一是具備初始化項目結(jié)構(gòu)、下載相關(guān)依賴包功能的 @chirono/medusa-cli,另外是約定好項目結(jié)構(gòu)與必要配置文件的 miniprogram-base 。
業(yè)務(wù)開發(fā)者只需要通過 npm 全局安裝 @chirono/medusa-cli 工具,便可以通過 medusa create  命令初始化一個工程項目,該工具還會提示必要的項目信息讓開發(fā)者輸入,用于完善業(yè)務(wù)項目的 package.json 文件。

結(jié)語

以上是我對 Medusa 這一工程的總結(jié),現(xiàn)在這一工程已經(jīng)進入較為穩(wěn)定的階段也已經(jīng)順利投入到多個實際項目當(dāng)中。對于上述的總結(jié)可能有某些部分寫得相對簡略,如果你卻有興趣我建議你直接下載源碼去研究,因為編碼的實際操作確實無法用三言兩語解釋清楚。我寫下這一篇文章主要想表達的是工程鏈路的完整性能夠為實際的項目開發(fā)產(chǎn)生相當(dāng)大的效益,而且實踐工程當(dāng)中不僅是單一工具的開發(fā),要將工具串起來。接下來我可能還會對UI打包、TS編譯、測試工具這些內(nèi)容進行知識總結(jié)。最后,感謝你的閱讀,如果你有疑問或是建議可以留言與我共同探討。


作者:饅頭君
來源:掘金
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。

相關(guān)案例查看更多