vue-cli 3.x 構建新專案,實現多頁,單頁webapp,並一鍵自動打包部署到測試環境

Edwardzh發表於2018-12-16

使用vue-cli 3.x構建新專案

之前使用vue-cli2.0構建的多頁專案,對腳手架擴充套件了一些功能,但是存在一些問題,趁現在升級了vue-cli 3.x順便把專案重構一下

擴充套件點

改造 vue 專案為多頁(多模組)、多應用,和單頁(單模組)共存的專案
改造npm run dev命令,支援單模組啟動除錯服務 和 全量專案啟動除錯服務
改造npm run build命令,改為構建指定應用並打包部署到不同的服務環境
複製程式碼

為什麼擴充套件?

vue-cli 2.0版本官方不支援多頁,且2.0使用的webpack構建任務不支援多執行緒以及DLL,全靠自己擴充套件,不便於維護。vue-cli 2.0在多頁數量較多的情況下,不管本地熱更新還是構建打包,都是非常慢的。 現在的工程大多存在多個子應用,且多個子應用通常使用一套元件,一套公共方法,但是子應用採用單獨發包迭代。所以支援多應用是非常有必要的

新建vue-cli 3.0專案

這個網上很多教程,這裡就說了,這篇檔案講的很詳細
[使用 vue-cli 3 快速建立 Vue 專案](https://segmentfault.com/a/1190000014627083)
複製程式碼

vue-cli 3.0官方支援多頁,重點在於vue.config.js檔案的配置

const path = require('path');
// 新建一個multipage.js檔案,用來處理vue載入模板的入口;
const pages = require('./config/multipage').getPages();

module.exports = {
    // 官方要求修改路徑在這裡做更改,預設是根目錄下,可以自行配置
    baseUrl: './',
    lintOnSave: false,
    productionSourceMap: false,
    // 在多核機器下會預設開啟。
    parallel: require('os').cpus().length > 1,
    pages,
    css: {                // css相關配置
        extract: true,    // 是否使用css分離外掛 ExtractTextPlugin
        sourceMap: false, // 開啟 CSS source maps?
        loaderOptions: {
            less: {
            javascriptEnabled: true
            }
        },             // css預設器配置項
        modules: false // 啟用 CSS modules for all css / pre-processor files.
    },

    chainWebpack: config => {
        if (process.env.NODE_ENV === 'production') {
            config.module.rule('images').use('url-loader').loader('url-loader').tap(options => {
                options.name = 'static/img/[name].[hash:8].[ext]';
                return options;
            });
            config.plugin('extract-css').tap(() => [
                {
                    filename: 'static/css/[name].[contenthash:8].css',
                    chunkFilename: 'static/css/[name].[contenthash:8].css'
                }
            ]);
        }
    },

    configureWebpack: config => {
        if (process.env.NODE_ENV === 'production') {
            config.output.path = path.join(__dirname, './dist')
            config.output.filename = 'static/js/[name].[contenthash:8].js'
            config.output.chunkFilename = 'static/js/[name].[contenthash:8].js'
        }
        Object.assign(config, {
            // 打包時webpack不打包進去
            externals: [
                {'vue': 'window.Vue'},
                {'vue-router': 'window.VueRouter'}
            ],
            // 開發生產共同配置
            resolve: {
                alias: {
                    '@': path.resolve(__dirname, './src'),
                    'assets': path.resolve(__dirname, './src/assets'),
                    'common': path.resolve(__dirname, './src/common'),
                    'components': path.resolve(__dirname, './src/components'),
                    'pages': path.resolve(__dirname, './src/pages'),
                    'vue$': 'vue/dist/vue.esm.js'
                }
            }
        });
    }
};

複製程式碼

說下配置檔案踩的坑

if (process.env.NODE_ENV === 'production') {
    config.output.path = path.join(__dirname, './dist')
    config.output.filename = 'static/js/[name].[contenthash:8].js'
    // 這裡是不支援直接修改publicPath路徑的,必須用官方推薦的 baseUrl。
    // config.output.publicPath = './'
    config.output.chunkFilename = 'static/js/[name].[contenthash:8].js'
}
複製程式碼

最後打包出來的目錄格式是這樣的

vue-cli 3.x 構建新專案,實現多頁,單頁webapp,並一鍵自動打包部署到測試環境

multipage.js檔案

const path = require('path');
const fs = require('fs');

const URL = process.env.url;            // 預設只載入一個檔案 singlepage || multipage
const NODE_ENV = process.env.NODE_ENV;  // process環境變數

if (NODE_ENV === 'production' && URL === undefined) throw new Error('當前打包命令缺少url引數!')

const config = {
    entry: 'index.js',
    html: 'index.html',
    pagesRoot: path.resolve(__dirname, '../src/pages')
};

const getRoutes = () => {
    const allRoutes = [];

    const findAllRoutes = (source, routes) => {
        const globFiles = fs.readdirSync(source);
        // 有URL 就預設載入那個指定的專案, 沒有就載入全部的 [ *.js ];
        const files = URL ? [globFiles.find(item => item.includes(URL))] : globFiles;
        files.forEach(filename => {
            const fullname = path.join(source, filename);
            const stats = fs.statSync(fullname);
            if (!stats.isDirectory()) return;
            // 檢測給定的路徑是否存在。
            if (fs.existsSync(`${fullname}/${config.html}`)) {
                routes.push(fullname);
            } else {
                findAllRoutes(fullname, routes);
            }
        });
    };
    findAllRoutes(config.pagesRoot, allRoutes);
    return allRoutes;
};

const getPages = () => {
    const pages = {};

    getRoutes().forEach(route => {
        let filename = route.slice(config.pagesRoot.length + 1);
        pages[filename] = {
            entry: `${route}/${config.entry}`,
            template: `${route}/${config.html}`,
            // 相容dev開發模式時 serve 全量專案和單個專案
            filename: URL ? config.html : `${filename}/${config.html}`
        };
    });
    // console.log(pages);
    return pages;
};

module.exports = {
    getRoutes,
    getPages
}
複製程式碼

src 目錄下

vue-cli 3.x 構建新專案,實現多頁,單頁webapp,並一鍵自動打包部署到測試環境

啟動專案 dev

    1.  npm run dev  (啟動全部專案) 包含多頁專案 和 單頁專案
  
    2.  建議啟動單個專案,編譯時間短,啟動快 ( url=專案名 npm run dev )
複製程式碼

打包專案並一鍵部署到測試環境

url=專案名 npm run testbuild
這裡打包後是使用node.js實現的自動上傳;config檔案下的upload.js檔案我之前介紹過可以看我上一篇文章。
複製程式碼
"scripts": {
    "dev": "vue-cli-service serve --open",
    "lint": "vue-cli-service lint",
    "testbuild": "vue-cli-service build && cross-env NODE_CONFIG=test node config/upload"
  },
複製程式碼

cli3.x以後尤大進行了更深的封裝, 啟動或者打包都是依靠這個vue-cli-service去執行的;

// 原始碼部分位置 node_modules\@vue\cli-service\bin\vue-cli-service.js
#!/usr/bin/env node

const semver = require('semver')
const { error } = require('@vue/cli-shared-utils')
const requiredVersion = require('../package.json').engines.node

if (!semver.satisfies(process.version, requiredVersion)) {
  error(
    `You are using Node ${process.version}, but vue-cli-service ` +
    `requires Node ${requiredVersion}.\nPlease upgrade your Node version.`
  )
  process.exit(1)
}

const Service = require('../lib/Service')
const service = new Service(process.env.VUE_CLI_CONTEXT || process.cwd())
// 主要核心功能在這裡;
const rawArgv = process.argv.slice(2)
const args = require('minimist')(rawArgv)
const command = args._[0]
// 這裡根據command的結果去執行是  run server 還是run build ;
service.run(command, args, rawArgv).catch(err => {
  error(err)
  process.exit(1)
})

複製程式碼

使用感受

修改後整體使用下來,無論是本地開發編譯,還是打包專案,提升都很明顯,感覺至少提升80%;
原因:cli3.x 升級了webpack4, 配置了多執行緒提升了速度,使用了快取,有些公共檔案不會被再次打包編譯;
複製程式碼

歡迎加我qq一起探討學習3544757498;

下一篇介紹本專案的技術選型和專案優化;

相關文章