vue-cli3单页构建大型项目方案


Posted in Javascript onApril 07, 2020

一、vue-cli3单页面构建方案

1、在目标文件夹内执行

vue ui ; 一个ui版界面,用于创建vue项目;

2、打开router文件夹内的index,看情况配置router的模式,是默认的hash还是history?ps:个人推介history模式,因为内嵌如app的H5页面的话,有可能某些app是不允许页面上带有'#'的,而hash会在url上利用#来做路由转发。ps:history模式在发布到服务器上需要nginx配置一下。详情请自行百度。

const router = new VueRouter({
 base: '/',
 mode: 'history', //还可设置为'hash'模式
 routes
})

3、在根目录新建vue.config.js,覆盖webpack配置,将如下内容copy到文件中,作为初始配置

// const webpack = require('webpack')

module.exports = {
  lintOnSave: false, // 禁止eslint
  devServer: {
    open: true, // 构建完成自动打开浏览器
  },

  configureWebpack: {
    plugins: [
      // 全局配置node_modules中的模块,使用时无需引入
      new webpack.ProvidePlugin({
        $: "jquery",
        jQuery: "jquery",
        "windows.jQuery": "jquery"
      })
    ]

  },

  // webpack 链接 API,用于生成和修改 webapck 配置
  chainWebpack: (config) => {
    // 取消 chunks,每个页面只对应一个单独的 JS / CSS
    config.optimization.splitChunks({
      cacheGroups: {}
    });

    // config
    //   .plugin('webpack-bundle-analyzer')
    //   .use(require('webpack-bundle-analyzer').BundleAnalyzerPlugin)
  },

  pluginOptions: {

  }
}

4、配置完这些后,npm run serve启动项目,会加载如下两个js

npm run serve

vue-cli3单页构建大型项目方案

app.js:是所有单页面首次渲染都必须加载的js,内部合并了框架及js(如vue、vue-x、vue-router及非异步组件但引用了的node_modules中的模块),及所有页面公用的模块。about.js:是每个页面独立的js,这个跟router中引用模块的方式有关。

具体详解如下:

1、

import Home from '../views/Home.vue'

这种引用方式引用页面模版组件,就不会出现about.js文件,因为属于同步模块,当前件建的js会被打包进app.js。但是此种随着页面的增多,公用的app.js会越来越大。看情况在app.js大小接受的前提下权衡使用;2、

const routes = [
 {
  path: '/',
  name: 'Home',
  // component: Home
  component: () => import(/* webpackChunkName: "home" */ '../views/Home.vue') // webpack的魔法注释,将拆分出的js命名为home
 },
 {
  path: '/about',
  name: 'About',
  // route level code-splitting
  // this generates a separate chunk (about.[hash].js) for this route
  // which is lazy-loaded when the route is visited.
  component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
 }
]

这种引用方式就是异步引用模版组件,不会将当前组建的js打包进app.js,就不会出现1种的问题。因为只要没有加载到对应页面,就不会加载对应页面的js。对应页面的js会最为独立的js单独的动态引入,如同上图的about.js,在进入about页面时才会引入。

3、如果在main.js中引入的node_modules包,则会直接打包进app.js,这个逃不掉。

ps:最终结论,建议每个页面都异步引用页面模版。

5、每个页面如果引了node_mudules就会存在相对应的vendors-home.js,如果没引入node_mudules的话,每个页面按需组件就不会存在vendors-home.js这个文件,如下图:

vue-cli3单页构建大型项目方案

vue-cli3单页构建大型项目方案

6、区分本地、测试、线上环境

ps:官网提供一种方案,但是需要建立多个环境配置的配置文件,嫌麻烦,就不使用官方的方式,使用如下插件拆分环境:

cross-env:https://github.com/kentcdodds/cross-env

cnpm i cress-env --save-dev // 更改node环境变量插件

之后在package.json中加入如下三行配置,即可区分本地、测试、线上环境

"scripts": {
  "serve": "cross-env NODE_ENV=development vue-cli-service serve",
  "test": "cross-env NODE_ENV=test vue-cli-service build",
  "build": "cross-env NODE_ENV=production vue-cli-service build"
 },

在vue.config.js中执行如下代码即可打印出当前环境。

console.log(process.env.NODE_ENV)

在src目录下新建config目录,进入目录,新建gateway.config.js文件用于配置不同环境接口host,代码如下:gateway.config.js文件内容如下:

// 开发环境地址(npm run serve)
const devHost = {
 // 接口地址域名相关
 baseApi: 'https://abc.com',

}

// 测试环境地址(npm run test)
const testHost = {
 // 接口地址域名相关
 baseApi: 'https://abc.com',

}

// 线上环境地址(npm run build)
const proHost = {
 // 接口地址域名相关
 baseApi: 'https://abc1.com',

}

// 区分环境选择静态资源地址
const env = process.env.NODE_ENV

let exportConfig = ''
if (env === 'production') {
 exportConfig = proHost
} else if (env === 'test') {
 exportConfig = testHost
} else {
 exportConfig = devHost
}

export default exportConfig

结束:之后只需要在接口api的js文件中引入此文件即可。发布时区分环境打包。

7、浅谈项目引入第三方插件方案

ps:原则:移动端单个js大小不超过200k;pc端单个js不超过400k;

1.vue模块化引入node_modules包插件:

前提,各个页面都是异步加载,这样的好处是单个页面的js不会被打包进公共app.js中。之后在单个js中引入第三方库。但是据测试:这种模块化引入第三方插件,比cdn模式引入的js体积至少要大2呗,因为webpack内部对每个第三方库进行了二次处理,会增大js体积。权衡js大小使用。

2.cdn模式引入第三方插件:

提供这种方式,是因为有些库是不支持vue的,只支持cdn模式引入,而且比较轻量级,可以选择这种方案,异步cdn模式引入第三方插件,这些方式最下方脚手架示例中都有demo;

8、项目中常用的打包插件及第三方库

1.vue https://cn.vuejs.org
2.vue-router https://router.vuejs.org
3.vue-x https://vuex.vuejs.org
4.sass https://www.sass.hk
5.axios http://www.axios-js.com/
6.normalize.css http://necolas.github.io/normalize.css/
7.n-zepto https://npm.taobao.org/package/n-zepto
8.webpack-bundle-analyzer https://github.com/webpack-contrib/webpack-bundle-analyzer

下方是vue-cli3内置插件(直接在vue.config.js中配置):

如下插件可参考vue-cli3官网配置方法:

https://cli.vuejs.org/zh/config/#css-sourcemap

9.autoprefixer:自动添加浏览器前缀。(如:-webkit-等)
10.url-loader:改变静态资源引用路径

11.ProvidePlugin:全局配置node_modules中的模块

具体配置方法如下(比较全的vue.config.js配置):

const webpack = require('webpack')

const processEnv = process.env.VUE_APP_ENV; // 区分环境(值:production、development、test)
const isPro = processEnv === 'production'; // 判断production环境

const outputDir = 'dist'; // 输出文件目录(默认dist)
const assetsDir = ''; // 配置放置生成的静态资源 (js、css、img、fonts) 的 (相对于 outputDir 的) 目录

// 区分环境选择cdn地址
let publicPath = '' // 静态资源引用路径
let fontPublicPath = '' // 字体图标引用的cdn路径
let imgPublicPath = '' // css引用图片的cdn路径(c2c/static/img)
if (processEnv === 'production') {
  publicPath = 'https://abc.com/c2c/shop' // 正式环境静态资源css、js等cdn路径
  fontPublicPath = `https://abc.com/c2c/shop/${assetsDir ? assetsDir + '/' : '/'}fonts` // 正式环境字体图标引用的cdn路径
  imgPublicPath = `https://abc.com/c2c/shop/${assetsDir ? assetsDir + '/' : '/'}/img` // 正式环境css引用图片的cdn路径
} else if (processEnv === 'test') {
  // publicPath = './' // 正式环境静态资源css、js等cdn路径
  publicPath = 'https://bcd.com/c2c/shop/dist' // 测试环境静态资源css、js等cdn路径
  fontPublicPath = ''
  imgPublicPath = ''
} else {
  publicPath = '/'
  fontPublicPath = ''
  imgPublicPath = ''
}

const devServerHost = 'localhost';
const devServerPort = '8080'; // 端口号
const devServerOpen = true; // 热启动后自动打开浏览器

module.exports = {

  // 配置生成dist里面static的cdn资源路径(测试环境为./,正式环境走cdn路径)
  publicPath: publicPath,

  // 输出文件目录(默认dist)
  outputDir,

  // 配置放置生成的静态资源 (js、css、img、fonts) 的 (相对于 outputDir 的) 目录
  assetsDir,

  devServer: {
    host: devServerHost,
    port: devServerPort,
    open: devServerOpen, // 构建完成自动打开浏览器


    // eslint检测影响代码编译,注释调不会影响代码编译
    // overlay: {
    //   warnings: true,
    //   errors: true
    // }
  },
  lintOnSave: processEnv === 'development' ? true : false, // 开发环境开启eslint,测试和线上编辑代码禁止eslint

  // webpack 配置,键值对象时会合并配置,为方法时会改写配置
  configureWebpack: config => {
    // 扩展资源,不将部分资源js等打入包内引用cdn资源
    let externals = {
      // 'swiper': 'Swiper',
    };
    config.externals = externals;

    //警告 webpack 的性能提示
    config.performance = {
      hints: isPro ? 'warning' : false, // 本地开发不显示警告
      // 入口起点的最大体积
      maxEntrypointSize: 512000, // 500kib
      // 生成文件的最大体积
      maxAssetSize: 307200, // 300kib
      // 只给出 js 文件的性能提示
      assetFilter(assetFilename) {
        return assetFilename.endsWith('.js');
      }
    };
  },

  // webpack 链接 API,用于生成和修改 webapck 配置
  chainWebpack: (config) => {
    // 取消 chunks,每个页面只对应一个单独的 JS / CSS
    config.optimization.splitChunks({
      cacheGroups: {}
    });

    // 全局配置node_modules中的模块,使用时无需引入
    config.plugin('provide').use(webpack.ProvidePlugin, [{
      $: "n-zepto",
      Zepto: "n-zepto",
      "window.Zepto": "n-zepto"
    }]);

    config.module
      .rule('images')
      .use('url-loader')
      .loader('url-loader')
      .tap(options => Object.assign(options, {
        limit: 10240, // 小于10k,压缩图片 => base64
        // limit: 3000,
        publicPath: imgPublicPath,
        name: `[name].[hash:8].[ext]`
      }))

    // 设置fonts字体文件引用的路径
    config.module
      .rule('fonts')
      .test(/\.(woff2?|eot|ttf|otf)(\?.*)?$/i)
      .use('url-loader')
      .loader('file-loader')
      .tap(options => Object.assign(options, {
        limit: 5000,
        publicPath: fontPublicPath,
        name: '[name].[hash:8].[ext]'
      }))


    // npm run report;打印app.js的模块报告,查看各个模块;
    if (processEnv === 'report') {
      config
        .plugin('webpack-bundle-analyzer')
        .use(require('webpack-bundle-analyzer').BundleAnalyzerPlugin)
    }

  },

  // css配置处理
  css: {
    // 是否使用css分离插件 ExtractTextPlugin;true:页面css独立分割,false:页面css同一打包;
    extract: true,
    // 开启 CSS source maps(默认false)线上关闭,测试和本地开启
    sourceMap: isPro ? false : true,
    // css预设器配置项
    loaderOptions: {
      sass: {
        // sass的公共方法和变量,需要预编译;
        prependData: `
          @import "@/assets/css/global.scss";
          @import "@/assets/css/func.scss";
        `
      },
      postcss: {
        plugins: [
          // 浏览器自动加前缀
          require('autoprefixer')({
            overrideBrowserslist: [
              "Android 4.0",
              "iOS 7",
              "Chrome > 31",
              "ff > 31",
              "ie >= 8"
            ]
          }),
        ]
      }

    },
    // 启用 CSS modules for all css / pre-processor files.
    requireModuleExtension: false
  },

  // 构建时开启多进程处理 babel 编译
  parallel: require('os').cpus().length > 1,

  pwa: {
    iconPaths: {
      favicon32: 'favicon.ico',
      favicon16: 'favicon.ico',
      appleTouchIcon: 'favicon.ico',
      maskIcon: 'favicon.ico',
      msTileImage: 'favicon.ico'
    },

  },

  // 第三方插件配置
  pluginOptions: {
    // ...
  }
}

9、一个基础配置较为完善的基于vue-cli3的单页面项目方案脚手架:
项目脚手架集合project-init
其中的cli-start-spa文件夹,内部readme有项目细节。

到此这篇关于vue-cli3单页构建大型项目方案的文章就介绍到这了,更多相关vue-cli3单页构建 内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
firefox下frameset取不到值的解决方法
Sep 06 Javascript
JavaScript高级程序设计(第3版)学习笔记10 再访js对象
Oct 11 Javascript
详解基于Bootstrap扁平化的后台框架Ace
Nov 27 Javascript
微信小程序 视图容器组件的详解及实例代码
Jan 19 Javascript
原生js简单实现放大镜特效
May 16 Javascript
php 修改密码实现代码
May 24 Javascript
JavaScript创建对象方式总结【工厂模式、构造函数模式、原型模式等】
Dec 19 Javascript
vue router 组件的高级应用实例代码
Apr 08 Javascript
小程序实现短信登录倒计时
Jul 12 Javascript
JS实现图片切换特效
Dec 23 Javascript
React冒泡和阻止冒泡的应用详解
Aug 18 Javascript
JavaScript 异步时序问题
Nov 20 Javascript
在Chrome DevTools中调试JavaScript的实现
Apr 07 #Javascript
《javascript设计模式》学习笔记四:Javascript面向对象程序设计链式调用实例分析
Apr 07 #Javascript
详解vue中在循环中使用@mouseenter 和 @mouseleave事件闪烁问题解决方法
Apr 07 #Javascript
《javascript设计模式》学习笔记三:Javascript面向对象程序设计单例模式原理与实现方法分析
Apr 07 #Javascript
flexible.js实现移动端rem适配方案
Apr 07 #Javascript
《javascript设计模式》学习笔记一:Javascript面向对象程序设计对象成员的定义分析
Apr 07 #Javascript
详解vue-flickity的fullScreen功能实现
Apr 07 #Javascript
You might like
shopex中集成的站长统计功能的代码简单分析
2011/08/11 PHP
JavaScript 中的事件教程
2007/04/05 Javascript
ASP小贴士/ASP Tips javascript tips可以当桌面
2009/12/10 Javascript
浅析js中取绝对值的2种方法
2013/07/09 Javascript
jquery.post用法之type设置问题
2014/02/24 Javascript
javascript处理表单示例(javascript提交表单)
2014/04/28 Javascript
document.write的几点使用心得
2014/05/14 Javascript
Node.js中使用Log.io在浏览器中实时监控日志(等同tail -f命令)
2014/09/17 Javascript
jQuery 判断是否包含在数组中Array[]的方法
2016/08/03 Javascript
利用jQuery实现打字机字幕效果实例代码
2016/09/02 Javascript
原生Javascript插件开发实践
2017/01/18 Javascript
canvas实现刮刮卡效果
2017/03/14 Javascript
vue.js 初体验之Chrome 插件开发实录
2017/05/13 Javascript
详解Node 定时器
2018/02/26 Javascript
vue 指令和过滤器的基本使用(品牌管理案例)
2019/11/04 Javascript
ES6 Iterator遍历器原理,应用场景及相关常用知识拓展详解
2020/02/15 Javascript
Vue路由切换页面不更新问题解决方案
2020/07/10 Javascript
Vue 实现对quill-editor组件中的工具栏添加title
2020/08/03 Javascript
[03:22]DOTA2超级联赛专访单车:找到属于自己的英雄
2013/06/08 DOTA
python中import学习备忘笔记
2017/01/24 Python
基于Python代码编辑器的选用(详解)
2017/09/13 Python
使用Python读取大文件的方法
2018/02/11 Python
基于python3实现socket文件传输和校验
2018/07/28 Python
python 输出所有大小写字母的方法
2019/01/02 Python
python虚拟环境的安装和配置(virtualenv,virtualenvwrapper)
2019/08/09 Python
pyqt5 QScrollArea设置在自定义侧(任何位置)
2019/09/25 Python
Python调用scp向服务器上传文件示例
2019/12/22 Python
在pycharm中创建django项目的示例代码
2020/05/28 Python
浅谈tensorflow中dataset.shuffle和dataset.batch dataset.repeat注意点
2020/06/08 Python
使用Html5实现异步上传文件,支持跨域,带有上传进度条
2016/09/17 HTML / CSS
Christys’ Hats官网:英国帽子制造商
2018/11/28 全球购物
杠杆的科学教学反思
2014/01/10 职场文书
安全生产先进个人材料
2014/02/06 职场文书
致垒球运动员加油稿
2014/02/16 职场文书
工厂仓管员岗位职责
2015/04/01 职场文书
Linux7.6二进制安装Mysql8.0.27详细操作步骤
2021/11/27 MySQL