vue简易微前端项目搭建(三):webpack相关配置

github传送门:
1、h5主项目
2、项目脚手架
3、子项目模板

系列文章传送门:
vue简易微前端项目搭建(一):项目背景及简介
vue简易微前端项目搭建(二):子项目模板及项目脚手架搭建
vue简易微前端项目搭建(三):webpack相关配置


1、概述

由于项目是基于vue-cli4改造的,所以webpack相关配置我们就在vue.config.js里操刀,没有该文件的直接在项目根目录新建vue.config.js即可,具体配置api参考官方文档(传送门

2、process.env

先说一下这个,因为后面会用到这里存储的变量值。
在系列文章上一篇中说到了.env文件,里面定义的变量会自动加入到process.env变量中,具体参考官方说明:传送门
这里再简单说明一下,先看目录:
在这里插入图片描述

(1) .env 这个是全局共用的

# 定义api地址的代理标识
VUE_APP_PROXY_CODE = '/proxy'

# 定义路由history模式是否开启(1开启 0关闭)
VUE_APP_HISTORY_OPEN = 0

# 定义路由history模式下项目在服务器上部署的基路径
VUE_APP_HISTORY_BASE = '/h5'

# 定义h5版本号
VUE_APP_H5_VERSION = '2.1.9.0'

(2).env.prod

这个是通过指定prod环境运行脚手架命令时会启用的

# 定义环境模式
VUE_APP_SERVER_ENV = 'prod'

# 定义服务器基础地址
VUE_APP_SERVER_URL = 'https://prod.com'

(3) 其他.env

其他的 .env.test 和 .env.beta 用法同上

(4)示例

例如运行脚手架命令:dyd start demo prod,能获取到的process.env变量有:

  • .env文件里启用的:
process.env.VUE_APP_PROXY_CODE
process.env.VUE_APP_HISTORY_OPEN
process.env.VUE_APP_HISTORY_BASE
process.env.VUE_APP_H5_VERSION
  • .env.prod文件里启用的:
process.env.VUE_APP_SERVER_ENV
process.env.VUE_APP_SERVER_URL
  • 还有获取到的子项目名(代码目录:/build/processEnv.js):
process.env.VUE_APP_PROJECT_NAME = process.argv[3].split('---')[1]
  • 还有自带的process.env.NODE_ENV
    我这里做了改动,本地运行时值为development,打包时值为production(代码目录:/build/processEnv.js):
// 设置NODE_ENV
const runType = process.argv[2]
if (runType === 'serve') {
  // 本地运行 npm run serve
  process.env.NODE_ENV = 'development'
} else if (runType === 'build') {
  // 打包项目 npm run build
  process.env.NODE_ENV = 'production'
}

3、vue.config.js

所有配置改动最终都汇聚在这里,按照vue-cli官方配置导出一个配置对象即可。

(1)获取子项目名

前面已经把获取到的子项目存储到process.env.VUE_APP_PROJECT_NAME 里了

const projectName = process.env.VUE_APP_PROJECT_NAME

(2)入口文件及html模板

在chainWebpack里进行配置:

chainWebpack: config => {
	// 入口文件
    config
      .entry('app')
      .clear()
      .add(`./src/projects/${projectName}/main.js`)
	// html模板文件
    config
      .plugin('html')
      .tap(args => {
        args[0].template = `./src/projects/${projectName}/index.html`
        args[0].templateParameters = {
          FAVICON_PATH: './favicon.ico'
        }
        return args
      })
  },

(3)打包输出目录

子项目按文件夹进行了划分,那打包后文件也同样需要划分开,并列在dist文件夹里即可

outputDir: `dist/${projectName}`,

(4)部署应用的基路径

开启路由history模式和不开启的配置不太一样:

  • 开启history模式时,基路径为 在服务器域名上部署的基目录 + 子项目名
  • 未开启时,打包项目用相对路径 ‘./’,本地运行用绝对路径 ‘/’
publicPath: +process.env.VUE_APP_HISTORY_OPEN
    ? `${process.env.VUE_APP_HISTORY_BASE}/${projectName}`
    : (process.env.NODE_ENV === 'production' ? './' : '/'),

process.env.VUE_APP_HISTORY_OPEN 和 process.env.VUE_APP_HISTORY_BASE 都配置在了.env文件里。

(5)代理服务配置

首先获取代理转发地址,还记得子项目模板里的config.js吗,本地dev启动就读取这个文件的地址:

// 获取代理服务器基础地址
let proxyServerUrl = process.env.VUE_APP_SERVER_URL
if (process.env.VUE_APP_SERVER_ENV === 'dev') {
  const ChildProjectConfig = require(resolve(`./src/projects/${projectName}/config.js`))
  proxyServerUrl = ChildProjectConfig.devServerUrl
}

然后配置devServer:

devServer: {
    host: '0.0.0.0',
    port: 8800,
    open: false, // 是否自动打开浏览器
    progress: false, // 是否显示进度
    proxy: {
      [process.env.VUE_APP_PROXY_CODE]: {
        target: proxyServerUrl,
        ws: true,
        changeOrigin: true,
        secure: false,
        pathRewrite: {
          ['^' + `${process.env.VUE_APP_PROXY_CODE}/${process.env.VUE_APP_SERVER_ENV}`]: ''
        }
      }
    }
  },

(6)alias快捷路径标识

也是在chainWebpack里配置:

chainWebpack: config => {
	config.resolve.alias
      .set('@@', resolve('./src/resources'))
      .set('@', resolve(`./src/projects/${projectName}`))
}

(7)去除prefetch

prefetch是一种性能优化方式,支持的浏览器会在空闲时提前下载解析,对于路由懒加载来说,这个功能会在你打开一个路由后把其他路由文件都加载下来,对于一整个关联性强的项目来说比较适用,比如后台管理系统,而对于本项目来说,主要应用场景是混合app内嵌h5页,页面比较分散,还有各种一次性活动页什么的,通常都会划分类别放在一个子项目里,不需要提前加载其他路由,所以不适合prefetch技术。

chainWebpack: config => {
	config.plugins
      .delete('prefetch')
}

(8)静态不打包目录

  • 有时候需要引用第三方打包好的js文件,而这种文件一般不能做二次打包,就需要个静态不打包目录,vue-cli官方提供的public文件夹是可以,但子项目里的都扔进去也不合适,还是单独配置为好,
  • 之前的子项目模板里默认有个static文件夹,就是预留给这个的,
  • 通过configureWebpack里配置plugins,插件使用copy-webpack-plugin
const CopyWebpackPlugin = require('copy-webpack-plugin')

configureWebpack: config => {
    const copyWebpackPlugin = new CopyWebpackPlugin([
	  {
	    from: Path.resolve(__dirname, '../src/projects/', projectName, 'static'),
	    to: 'static',
	    ignore: ['.*']
	  }
	])
    // 更新config
    config.plugins = [...config.plugins, copyWebpackPlugin]
  },

4、完整代码

vue.config.js

/**
 * Created by hanxueqiang on 19/11/13
 */
require('./build/processEnv.js')
const Path = require('path')
const Plugins = require('./build/plugins')

const projectName = process.env.VUE_APP_PROJECT_NAME

function resolve (dir) {
  return Path.resolve(__dirname, dir)
}

// 获取代理服务器基础地址
let proxyServerUrl = process.env.VUE_APP_SERVER_URL
if (process.env.VUE_APP_SERVER_ENV === 'dev') {
  const ChildProjectConfig = require(resolve(`./src/projects/${projectName}/config.js`))
  proxyServerUrl = ChildProjectConfig.devServerUrl
}

module.exports = {
  publicPath: +process.env.VUE_APP_HISTORY_OPEN
    ? `${process.env.VUE_APP_HISTORY_BASE}/${projectName}`
    : (process.env.NODE_ENV === 'production' ? './' : '/'),
  outputDir: `dist/${projectName}`,
  productionSourceMap: false,
  lintOnSave: process.env.NODE_ENV !== 'production',

  // 开发环境服务配置
  devServer: {
    host: '0.0.0.0',
    port: 8800,
    open: false,
    progress: false,
    proxy: {
      [process.env.VUE_APP_PROXY_CODE]: {
        target: proxyServerUrl,
        ws: true,
        changeOrigin: true,
        secure: false,
        pathRewrite: {
          ['^' + `${process.env.VUE_APP_PROXY_CODE}/${process.env.VUE_APP_SERVER_ENV}`]: ''
        }
      }
    }
  },

  // 合并webpack配置
  configureWebpack: config => {
    // 性能提示
    let myPerformance = {}
    if (process.env.NODE_ENV === 'production') {
      myPerformance = {
        hints: 'warning',
        maxEntrypointSize: 1024000,
        maxAssetSize: 1024000
      }
      config.plugins.forEach(v => {
        if (v.constructor.name === 'MiniCssExtractPlugin') {
          // 去除 mini-css-extract-plugin 警告
          v.options.ignoreOrder = true
        }
      })
    }
    // 更新config
    config.plugins = [...config.plugins, ...Plugins]
    config.performance = { ...config.performance, ...myPerformance }
  },

  // 修改webpack配置
  chainWebpack: config => {
    config.resolve.alias
      .set('@@', resolve('./src/resources'))
      .set('@', resolve(`./src/projects/${projectName}`))

    config
      .entry('app')
      .clear()
      .add(`./src/projects/${projectName}/main.js`)

    config
      .plugin('html')
      .tap(args => {
        args[0].template = `./src/projects/${projectName}/index.html`
        args[0].templateParameters = {
          FAVICON_PATH: './favicon.ico'
        }
        return args
      })

    // config.plugins
    //   .delete('preload')
    config.plugins
      .delete('prefetch')

    // chunk分离优化
    config.optimization
      .splitChunks({
        chunks: 'all',
        maxAsyncRequests: 8,
        maxInitialRequests: 6,
        minSize: 20000,
        cacheGroups: {
          vue: {
            name: 'chunk-vue',
            test: /[\\/]node_modules[\\/](vue|vue-router)[\\/]/,
            priority: 40
          },
          vconsole: {
            name: 'chunk-vconsole',
            test: /[\\/]node_modules[\\/]vconsole[\\/]/,
            priority: 30
          },
          vendors: {
            name: 'chunk-vendors',
            test: /[\\/]node_modules[\\/]/,
            priority: -10,
            chunks: 'initial'
          },
          common: {
            name: 'chunk-common',
            minChunks: 2,
            priority: -20,
            chunks: 'initial',
            reuseExistingChunk: true
          }
        }
      })
  },

  // 指定babel-loader要编译的node_modules包
  transpileDependencies: [],

  css: {
    loaderOptions: {
      less: {
        globalVars: {
          '@imgBaseGlobal': '~@@/assets/images/',
          '@imgBase': '~@/assets/images/'
        }
      }
    }
  }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值