vue多页面自动化编译

476 阅读3分钟

基于vue-cli3的自动化多页面模板,在网上资源文章及自己需求的推动下,可以各页面独立资源分文件夹编译和原生所有资源统一编译.

正文

大家可以直接使用我改好的初始模板.

自己搭建

  1. 创建自动化脚本 在项目根目录创建script文件夹,里面创建两个文件splitBuild.jsgetPages.js.

getPages.js

// getPages.js 自动获取目录结构
const glob = require('glob')
let pages = {}
module.exports.pages = function () {
  glob.sync('./src/pages/*/*.js').forEach(filepath => {
    let fileList = filepath.split('/')
    let fileName = fileList[fileList.length - 2]
    pages[fileName] = {
      entry: `src/pages/${fileName}/${fileName}.js`,
      // 模板来源
      template: `src/pages/${fileName}/${fileName}.html`,
      // 在 dist/index.html 的输出
      filename: process.env.VUE_APP_TITLE !== 'ps' ? `${fileName}.html` : `${fileName}/${fileName}.html`,
      // 提取出来的通用 chunk 和 vendor chunk。
      chunks: ['chunk-vendors', 'chunk-common', fileName]
    }
  })
  return pages
}

splitBuild.js

// splitBuild.js 分开编译资源处理脚本
var fs = require('fs')
const glob = require('glob')
const config = require('../vue.config.js')

const publicPath = config.publicPath || ''
const outputDir = config.outputDir || 'dist'
/**
 * js文件copy
 * @param src
 * @param dst
 */
var callbackFileJs = function (src, dst) {
  fs.readFile(src, 'utf8', function (error, data) {
    if (error) {
      // eslint-disable-next-line no-console
      console.log(error)
      return false
    }
    fs.writeFile(dst, data.toString(), 'utf8', function (error) {
      if (error) {
        // eslint-disable-next-line no-console
        console.log(error)
        return false
      }
      if (dst.includes('.map')) {
        // let srcName = src.split('/')[4]
        // fs.unlink(`./${outputDir}/js/${srcName}.map`,function () { // 删除map
        // })
        // fs.unlink(`./${outputDir}/js/${srcName}`,function () { // 删除js
        // })
      } else { // JS写入成功
        callbackFileJs(dst, `${dst}.map`)
      }
    })
  })
}
// 复制目录
glob.sync(`./${outputDir}/js/*.js`).forEach((filepath, name) => {
  let fileNameList = filepath.split('.')
  let fileName = fileNameList[1].split('/')[3]// 多页面页面目录
  let copyName = filepath.split('/')[3]
  let changeDirectory = `./${outputDir}/${fileName}/js`// 多页面JS文件地存放址
  if (!fileName.includes('chunk-')) {
    // eslint-disable-next-line
    fs.exists(changeDirectory, function (exists) {
      if (exists) {
        // console.log(`${fileName}下JS文件已经存在`)
        callbackFileJs(filepath, `${changeDirectory}/${copyName}`)
      } else {
        fs.mkdir(changeDirectory, function () {
          callbackFileJs(filepath, `${changeDirectory}/${copyName}`)
          // console.log(`${fileName}下JS文件创建成功`)
        })
      }
    })
  }
})

/**
 * css文件拷贝
 * @param src
 * @param dst
 */
var callbackFileCss = function (src, dst) {
  fs.readFile(src, 'utf8', function (error, data) {
    if (error) {
      // eslint-disable-next-line no-console
      console.log(error)
      return false
    }
    fs.writeFile(dst, data.toString(), 'utf8', function (error) {
      if (error) {
        // eslint-disable-next-line no-console
        console.log(error)
        PromiseRejectionEvent(error)
        return false
      }
      // console.log('CSS写入成功')
      fs.unlink(src, function () { // css删除成功
      })
    })
  })
}
// 复制目录
glob.sync(`./${outputDir}/css/*.css`).forEach((filepath, name) => {
  let fileNameList = filepath.split('.')
  let fileName = fileNameList[1].split('/')[3]// 多页面页面目录
  let copyName = filepath.split('/')[3]
  let changeDirectory = `./${outputDir}/${fileName}/css`// 多页面JS文件地存放址
  if (!fileName.includes('chunk-')) {
    /* eslint-disable-next-line */
    fs.exists(changeDirectory, function (exists) {
      if (exists) {
        // console.log(`${fileName}下CSS文件已经存在`)
        callbackFileCss(filepath, `${changeDirectory}/${copyName}`)
      } else {
        fs.mkdir(changeDirectory, function () {
          callbackFileCss(filepath, `${changeDirectory}/${copyName}`)
          //   console.log(`${fileName}下CSS文件创建成功`)
        })
      }
    })
  }
})

/**
 * html文件替换
 * @param src
 * @param dst
 */
var callbackFile = function (src, dst, name, filepath) {
  const index = publicPath.lastIndexOf('/')
  let pt = publicPath
  if (index !== -1) {
    const count = publicPath.length
    if (index + 1 === count) {
      pt = publicPath.slice(0, index - 1)
    }
  }

  fs.readFile(src, 'utf8', function (error, data) {
    if (error) {
      // eslint-disable-next-line no-console
      console.log(error)
      return false
    }
    let regCss = new RegExp(pt + '/css/' + name + '', 'g')
    let regJs = new RegExp(pt + '/js/' + name + '', 'g')
    let htmlContent = data.toString().replace(regCss, `./css/${name}`).replace(regJs, `./js/${name}`)
    fs.writeFile(dst, htmlContent, 'utf8', function (error) {
      if (error) {
        // eslint-disable-next-line no-console
        console.log(error)
        return false
      }
      // console.log('html重新写入成功')
      if (src.indexOf('/index.html') === -1) {
        fs.unlink(src, function () {
          //  console.log('html删除成功')
        })
      }
      fs.unlink(filepath, function () { // css删除成功
      })
      fs.unlink(filepath + '.map', function () { // css删除成功
      })
    })
  })
}
// 复制目录
glob.sync(`./${outputDir}/js/*.js`).forEach((filepath, name) => {
  let fileNameList = filepath.split('.')
  let fileName = fileNameList[1].split('/')[3]// 多页面页面目录
  let thisDirectory = `./${outputDir}/${fileName}/${fileName}.html`// 多页面JS文件地存放址
  let changeDirectory = `./${outputDir}/${fileName}/index.html`// 多页面JS文件地存放址
  if (!fileName.includes('chunk-')) {
    callbackFile(thisDirectory, changeDirectory, fileName, filepath)
  }
})

config配置

// vue.config.js
let pageMethod = require('./script/getPages.js')
const pages = pageMethod.pages()
// build-s编译不能将publicPath设置为'./''',会导致相对路径资源路径混乱
module.exports = {
  pages,
  publicPath: '/',
  outputDir: 'dist'
}

package.json

{
  ...
  "scripts": {
    "serve": "vue-cli-service serve --open ",
    "build-s": "vue-cli-service build --mode ps && node script/splitBuild.js",
    "build": "vue-cli-service build",
    ...
  },
    ...
}

使用说明

  1. 在src中创建pages文件夹

    title

  2. pages中创建的每一个文件夹就是一个单页面目录

    title

  3. 我们在对应单页面目录里创建对应html,vue及js文件即可.

    title

// html 就是页面的初始html(传统项目一般在public里面)
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
    <title>hello-world</title>
  </head>
  <body>
    <noscript>
      <strong>We're sorry but hello-world doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
    </noscript>
    <div id="app"></div>
    <!-- built files will be auto injected -->
  </body>
</html>
// js文件  项目初始化js
import Vue from 'vue'
import App from './index.vue'

Vue.config.productionTip = false

new Vue({
  render: h => h(App)
}).$mount('#app')
<template>
  <div id="app">
    <img alt="Vue logo" src="../../assets/logo.png">
    <p>页面2URL:http://localhost:8080/index2/</p>
  </div>
</template>

<script>
// vue主页面
export default {
  name: 'app'
}
</script>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

不足之处,欢迎访问DLLCN的学习笔记进行批评与讨论,一起成长,一起学习.