改造vue-cli,讓它更好用

vue-cli真的很好用?

vue-cli是一個整合了webpack+vue的腳手架,經過這個腳手架,咱們能夠很方便地建立一個vue項目,甚至引入了vuex和vue-router。webpack的配置對用戶來講是透明,用戶無需關注webpack的詳細配置,從而提升開發效率。
那麼vue-cli真的很好用嗎?讓咱們來看看vue-cli產生的Webpack配置。首先咱們看下入口文件配置:css

entry: {
    app: './src/main.js'
 }
複製代碼

很明顯,這是一個單入口文件,結合vue-router是能夠實現單頁面項目,打包起來也很方便,只有一個html文件和對應的靜態文件。這個優勢同時也是缺點,即若是咱們的項目比較龐大,那麼打包後全部的邏輯和業務都在一個文件裏面。有幾個缺點:html

  1. 全部邏輯和業務在一個頁面,致使頁面加載慢
  2. 打包和編譯的時候很慢,下降開發效率
  3. 高度耦合,打包的時候,若是有一個地方出錯,打包部署後,會致使整個網站都沒法訪問

這些缺點也是挺致命的,想一想若是你打包的時候調用了一個undefined方法,而後疏忽了發佈到外網去,大家老闆接下來就要找你好好聊天了。vue

基於以上,怎麼改進vue-cli建立的項目呢?答案固然就是分模塊了,對webpack配置進行修改,打包和編譯都按模塊來,這樣就不會把全部的邏輯都放入一個頁面內,編譯和打包都是按模塊了,下降耦合度,利於分工開發(一我的一個模塊)。node

改造

1.修改目錄結構:

原先的結構:webpack

改造後的:

modules #全部模塊文件夾
└───   assets #全部模塊共用的靜態文件
│    │   css
│    │   img
│    │   js
└───   common #全部模塊公用的js代碼,好比util.js
└───   components #全部模塊公用vue子模塊,好比header.vue
└───src #全部模塊的源碼文件夾
│   └─── module_name #模塊名
│   │     └─── assets #該模塊特有的靜態文件
│   │           │   css
│   │           │   img
│   │           │   js
│   │     └─── components #該模塊特用vue子模塊
│   │     └─── router #該模塊特用vue路由設置
│   │     └─── util #該模塊特用共有類js
│   │     │  App.vue #容器
│   │     │  index.html #模塊模板文件
│   │     │  main.js #模塊入口文件,文件名不要修改!!!
複製代碼

咱們先看最主要的修改,即添加了modules文件夾,modules下的src文件夾下就是全部模塊了,多個模塊有共享的assets和components,各個模塊也有各自的assets和components。經過對比,咱們能夠知道,其實就是將vue-cli的src下單個模塊劃分紅爲多個模塊。固然,各個模塊若是你想按照原來vue-cli產生的模式進行開發也是能夠的,各個模塊可大可小,不過建議各個模塊不要太大,否則分模塊的意義就不大了。git

2.修改webpack配置文件

一、修改webpack.base.config.js入口文件:github

entry: {
    app: utils.getEntry() // 以前是./src/main.js
}
複製代碼

utils.getEntry獲取當前正在開發的模塊的入口文件,因此咱們須要一個方法能夠獲取到當前正在運行的模塊的方法,這裏個人思路就是在咱們運行npm run sart/build的時候,去執行一個js文件,這個js文件能夠經過prompt獲取用戶輸入他想要運行的模塊,而後再啓動webpack服務器的時候將當前要運行的模塊做爲參數傳入。web

二、添加start.js/build.js 因此在command文件夾下添加start.js文件,內容以下:vue-router

const exec = require('child_process').exec
const { prompt } = require('inquirer')
const chalk = require('chalk')
// 詢問用戶想運行哪一個模塊,放入module變量當中
const question = [
  {
    type: 'input',
    name: 'module',
    message: 'Module name:',
    validate (val) {
      if (val === '') {
        return 'Module name is required!'
      } 
      return true
    }

  }
]
module.exports = prompt(question).then(({module}) => {
  // 要運行的模塊做爲參數傳給dev-server.js
  let cmdStr = `node ./build/dev-server.js ${module}`
  var child = exec(cmdStr)
  child.stdout.on('data', function(data) {
    console.log('stdout: ' + data)
  })
  child.stderr.on('data', function(err) {
    console.log(err)
    process.exit()
  })
})
複製代碼

build.js內容以下:vuex

const { prompt } = require('inquirer')
const exec = require('child_process').exec
const chalk = require('chalk')
const ora = require('ora')

const question = [
  {
    type: 'input',
    name: 'module',
    message: 'Module name:',
    validate (val) {
      if (val === '') {
        return 'Module name is required!'
      } 
      return true
    }
  }
]

module.exports = prompt(question).then(({module}) => {
  const spinner = ora(`Building ${module}...`)
  
  spinner.start()
  // 要運行的模塊做爲參數傳給build.js
  var child = exec(`node ./build/build.js ${module}`)
  child.stdout.on('data', (data) => {
    console.log('stdout: ' + data)
  })

  child.stderr.on('data', function(err) {
    console.log(chalk.red(`\n building ${module} error`))
    console.log(chalk.red(err))
    process.exit()
  })

  child.on('close', function(code) {
    spinner.stop()
    console.log(chalk.green('\n √ Build completed!'))    
  })
})
複製代碼

node運行的時候傳入參數後,就能夠經過process.argv獲取了,由於咱們傳入的是第二個參數,因此process.argv[2]就是咱們輸入的模塊名了

三、添加utils.js輔助方法

// 獲取項目路徑根路徑
exports.getProjectPath = () => {
  console.log(fs.realpathSync(process.cwd()))
  return fs.realpathSync(process.cwd())
}
// 獲取當前開發模塊的路徑, 如modules/views/test/
exports.getModulePath = () => {
  var moduleName = process.argv[2]
  return exports.getProjectPath() + '/modules/src/' + moduleName
}
複製代碼

所以獲取咱們當前模塊的入口文件是這樣的:

//獲取子模塊的入口文件,如modules/views/test/main.js
exports.getEntry = () => {
  return exports.getModulePath() + '/main.js'
}
複製代碼

須要打包的模塊的文件是這樣的:

// 根據當前正在開發的模塊,獲取想要打包的文件
exports.getOuputFileName = () => {
  var moduleName = process.argv[2]
  return exports.getProjectPath() + `/../${moduleName}/index.html`
}
複製代碼

四、固然咱們打包的時候,打包文件是須要放在不一樣的模塊下的,而不是全都都打包到一個html下,因此修改webpack.prod.config.js文件,修改HtmlWebpackPlugin插件,指定打包的路徑

new HtmlWebpackPlugin({
  filename: utils.getOuputFileName(),
  template: utils.getModuleTemplate(),
  inject: true,
  minify: {
    removeComments: true,
    collapseWhitespace: true,
    removeAttributeQuotes: true
  }
複製代碼

五、修改package.json文件

"scripts": {
    "start": "node command/start.js cross-env NODE_ENV=develoment",
    "build": "node command/build.js"
  },
複製代碼

這樣基本就完成了開發運行時,按照各個模塊運行/打包了。

你們有沒有發現,其實咱們各個模塊之間的目錄結構都差很少,每次新建模塊的時候都須要去複製黏貼,很機械化,那麼咱們能夠作到自動化。

自動化添加模塊

基本思路是咱們把模塊固定的結構放在github上,附上我本身的連接:github.com/VikiLee/mod…
而後使用download-git-repo去下載到本地來。固然咱們須要經過prompt詢問用戶想要新建的模塊名,而後從github上download下來到這個模塊文件夾下就ok了,在command文件夾下新建create.js,內容以下:

const download = require('download-git-repo')
const { prompt } = require('inquirer')
const ora = require('ora')
const chalk = require('chalk')
const fs = require('fs')

var question = [
  {
    type: 'input',
    name: 'moduleName',
    message: 'Please input module name:',
    validate(val) {
      if(val === ''){
        return 'Module name is required'
      }
      return true
    }
  }
]

module.exports = prompt(question).then(({moduleName}) => {

  //模塊存在
  if (fs.existsSync(`./modules/src/${moduleName}`)) {
    console.log(chalk.red(`Module '${moduleName}' exists!`))
    process.exit()
  }

  const spinner = ora('Downloading template...')
  
  spinner.start()
  download(`VikiLee/module_tempate#master`, `./modules/src/${moduleName}`, (err) => {
    if (err) {
      console.log(chalk.red(err))
      process.exit()
    }
    spinner.stop()
    console.log(chalk.green('New module has been created successfully!'))
  })
})
複製代碼

同時修改package.json文件,添加create命令

"scripts": {
    "create": "node command/create.js",
    "start": "node command/start.js cross-env NODE_ENV=develoment",
    "build": "node command/build.js"
  },
複製代碼

這樣就經過自動化的方式新建模塊了。

git地址:github.com/VikiLee/web…

相關文章
相關標籤/搜索