vue-cli 3.x 构建新项目,实现多页,单页webapp,并一键自动打包部署到测试环境

使用vue-cli 3.x构建新项目

以前使用vue-cli2.0构建的多页项目,对脚手架扩展了一些功能,可是存在一些问题,趁如今升级了vue-cli 3.x顺便把项目重构一下javascript

扩展点css

改造 vue 项目为多页(多模块)、多应用,和单页(单模块)共存的项目
改造npm run dev命令,支持单模块启动调试服务 和 全量项目启动调试服务
改造npm run build命令,改成构建指定应用并打包部署到不一样的服务环境
复制代码

为何扩展?html

vue-cli 2.0版本官方不支持多页,且2.0使用的webpack构建任务不支持多线程以及DLL,全靠本身扩展,不便于维护。vue-cli 2.0在多页数量较多的状况下,无论本地热更新仍是构建打包,都是很是慢的。 如今的工程大多存在多个子应用,且多个子应用一般使用一套组件,一套公共方法,可是子应用采用单独发包迭代。因此支持多应用是很是有必要的vue

新建vue-cli 3.0项目java

这个网上不少教程,这里就说了,这篇文件讲的很详细
[使用 vue-cli 3 快速建立 Vue 项目](https://segmentfault.com/a/1190000014627083)
复制代码

vue-cli 3.0官方支持多页,重点在于vue.config.js文件的配置node

const path = require('path');
// 新建一个multipage.js文件,用来处理vue加载模板的入口;
const pages = require('./config/multipage').getPages();
const env = process.env.NODE_ENV;

module.exports = {
    // 官方要求修改路径在这里作更改,默认是根目录下,能够自行配置
    baseUrl: env === 'development' ? '/' : './',
    lintOnSave: false,
    productionSourceMap: false,
    // 在多核机器下会默认开启。
    parallel: require('os').cpus().length > 1,
    pages,
    css: {                // css相关配置
        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'
                }
            }
        });
    }
};

复制代码

说下配置文件踩的坑webpack

// 1
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'
}

// 2.我配置的项目是打包时vue和vue-router不打包进去,为了减小打包后的代码体积(经过script引入vue), 
这里你若是要打包在项目里面 externals也能够直接注释掉让(vue和vue-router参与项目打包);
Object.assign(config, {
    externals: [
        {'vue': 'window.Vue'},
        {'vue-router': 'window.VueRouter'}
    ],
    ....
})
复制代码

最后打包出来的目录格式是这样的web

multipage.js文件vue-router

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 ];
        let files = []
        
        if (URL) {
            const item = globFiles.find(item => item == URL);
            if (item === undefined) throw new Error('url项目不存在,请检查!');
            files.push(item);
        } else {
            files = globFiles;
        }
        
        files.forEach(filename => {
            const fullname = path.join(source, filename);
            const stats = fs.statSync(fullname);
            // 不是文件目录 return;
            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}`
        };
    });
 
    return pages;
};

module.exports = {
    getRoutes,
    getPages
}
复制代码

src 目录下vue-cli

package.json的依赖:

"devDependencies": {
    "@vue/cli-plugin-babel": "3.0.0",
    "@vue/cli-plugin-eslint": "3.0.0",
    "@vue/cli-service": "3.0.0",
    "cross-env": "^5.2.0",
    "less": "^3.9.0",
    "less-loader": "^4.1.0",
    "postcss-px2rem": "^0.3.0",
    "vue-template-compiler": "2.5.17"
  },
复制代码

启动项目 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;

下一篇介绍本项目的技术选型和项目优化;

相关文章
相关标签/搜索