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

使用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'
}
复制代码

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

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 目录下

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

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

转载于:https://juejin.im/post/5c15c82ce51d452d036d482e

你可能感兴趣的:(vue-cli 3.x 构建新项目,实现多页,单页webapp,并一键自动打包部署到测试环境...)