This commit is contained in:
sunnie 2020-04-20 18:07:56 +08:00
parent 452ad3d73e
commit 6c4a6a6f6a
12 changed files with 336 additions and 259 deletions

180
README.md
View File

@ -2,7 +2,7 @@
基于 vue-cli3.0+webpack 4+vant ui + sass+ rem 适配方案+axios 封装,构建手机端模板脚手架 基于 vue-cli3.0+webpack 4+vant ui + sass+ rem 适配方案+axios 封装,构建手机端模板脚手架
[关于项目介绍](https://juejin.im/post/5cfefc73f265da1bba58f9f7) 掘金: [vue-cli4 vant rem 移动端框架方案](https://juejin.im/post/5cfefc73f265da1bba58f9f7)
[demo](https://solui.cn/vue-h5-template/#/)建议手机端查看 [demo](https://solui.cn/vue-h5-template/#/)建议手机端查看
@ -13,6 +13,19 @@
本示例 Node.js 12.14.1 本示例 Node.js 12.14.1
### 启动项目
```bash
git clone https://github.com/sunniejs/vue-h5-template.git
cd vue-h5-template
npm install
npm run serve
```
<span id="top">目录</span> <span id="top">目录</span>
- [√ Vue-cli4](https://cli.vuejs.org/zh/guide/) - [√ Vue-cli4](https://cli.vuejs.org/zh/guide/)
@ -30,10 +43,9 @@
- [√ 配置 打包分析](#bundle) - [√ 配置 打包分析](#bundle)
- [√ 配置 externals 引入 cdn 资源 ](#externals) - [√ 配置 externals 引入 cdn 资源 ](#externals)
- [√ 去掉 console.log ](#console) - [√ 去掉 console.log ](#console)
- [√ splitChunks ](#console) - [√ splitChunks 单独打包第三方模块](#chunks)
- [√ 添加 IE 兼容 ](#ie) - [√ 添加 IE 兼容 ](#ie)
* Vuex * Vuex
* Axios 封装 * Axios 封装
* 生产环境 cdn 优化首屏加速 * 生产环境 cdn 优化首屏加速
@ -466,7 +478,7 @@ module.exports = {
outputDir: 'dist', // 生产环境构建文件的目录 outputDir: 'dist', // 生产环境构建文件的目录
assetsDir: 'static', // outputDir的静态资源(js、css、img、fonts)目录 assetsDir: 'static', // outputDir的静态资源(js、css、img、fonts)目录
lintOnSave: false, lintOnSave: false,
productionSourceMap: !IS_PROD, // 生产环境的 source map productionSourceMap: false, // 如果你不需要生产环境的 source map可以将其设置为 false 以加速生产环境构建。
devServer: { devServer: {
port: 9020, // 端口号 port: 9020, // 端口号
open: false, // 启动后打开浏览器 open: false, // 启动后打开浏览器
@ -524,9 +536,9 @@ export function getUserInfo(params) {
### <span id="alias">✅ 配置 alias 别名 </span> ### <span id="alias">✅ 配置 alias 别名 </span>
```javascript ```javascript
const path = require("path"); const path = require('path')
const resolve = dir => path.join(__dirname, dir); const resolve = dir => path.join(__dirname, dir)
const IS_PROD = ["production", "prod"].includes(process.env.NODE_ENV); const IS_PROD = ['production', 'prod'].includes(process.env.NODE_ENV)
module.exports = { module.exports = {
chainWebpack: config => { chainWebpack: config => {
@ -538,40 +550,52 @@ module.exports = {
.set('views', resolve('src/views')) .set('views', resolve('src/views'))
.set('components', resolve('src/components')) .set('components', resolve('src/components'))
} }
}; }
``` ```
[▲ 回顶部](#top) [▲ 回顶部](#top)
### <span id="bundle">✅ 配置 打包分析 </span> ### <span id="bundle">✅ 配置 打包分析 </span>
```javascript ```javascript
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer") const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
.BundleAnalyzerPlugin;
module.exports = { module.exports = {
chainWebpack: config => { chainWebpack: config => {
// 打包分析 // 打包分析
if (IS_PROD) { if (IS_PROD) {
config.plugin("webpack-report").use(BundleAnalyzerPlugin, [ config.plugin('webpack-report').use(BundleAnalyzerPlugin, [
{ {
analyzerMode: "static" analyzerMode: 'static'
} }
]); ])
} }
} }
}; }
``` ```
```bash ```bash
npm run build npm run build
``` ```
[▲ 回顶部](#top) [▲ 回顶部](#top)
### <span id="proxy">✅ 配置 externals 引入 cdn 资源 </span> ### <span id="proxy">✅ 配置 externals 引入 cdn 资源 </span>
这个版本 CDN 不再引入,我测试了一下使用引入 CDN 和不使用,不使用会比使用时间少。网上不少文章测试 CDN 速度块,这个开发者可
以实际测试一下。
另外项目中使用的是公共 CDN 不稳定,域名解析也是需要时间的(如果你要使用请尽量使用同一个域名)
因为页面每次遇到`<script>`标签都会停下来解析执行,所以应该尽可能减少`<script>`标签的数量 `HTTP`请求存在一定的开销100K
的文件比 5 个 20K 的文件下载的更快,所以较少脚本数量也是很有必要的
暂时还没有研究放到自己的 cdn 服务器上。
```javascript ```javascript
const defaultSettings = require('./src/config/index.js') const defaultSettings = require('./src/config/index.js')
const name = defaultSettings.title || 'vue mobile template' const name = defaultSettings.title || 'vue mobile template'
const IS_PROD = ["production", "prod"].includes(process.env.NODE_ENV); const IS_PROD = ['production', 'prod'].includes(process.env.NODE_ENV)
// externals // externals
const externals = { const externals = {
@ -581,45 +605,57 @@ const externals = {
vant: 'vant', vant: 'vant',
axios: 'axios' axios: 'axios'
} }
// cdn // CDN外链会插入到index.html中
const cdn = { const cdn = {
css: ['https://cdn.jsdelivr.net/npm/vant@beta/lib/index.css'], // 开发环境
js: [ dev: {
'https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js', css: [],
'https://cdnjs.cloudflare.com/ajax/libs/vue-router/3.0.6/vue-router.min.js', js: []
'https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.min.js', },
'https://cdnjs.cloudflare.com/ajax/libs/vuex/3.1.1/vuex.min.js', // 生产环境
'https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/crypto-js.min.js', build: {
'https://cdn.jsdelivr.net/npm/vant@beta/lib/vant.min.js' css: ['https://cdn.jsdelivr.net/npm/vant@2.4.7/lib/index.css'],
] js: [
'https://cdn.jsdelivr.net/npm/vue@2.6.11/dist/vue.min.js',
'https://cdn.jsdelivr.net/npm/vue-router@3.1.5/dist/vue-router.min.js',
'https://cdn.jsdelivr.net/npm/axios@0.19.2/dist/axios.min.js',
'https://cdn.jsdelivr.net/npm/vuex@3.1.2/dist/vuex.min.js',
'https://cdn.jsdelivr.net/npm/vant@2.4.7/lib/index.min.js'
]
}
} }
module.exports = { module.exports = {
configureWebpack: config => { configureWebpack: config => {
config.name = name config.name = name
// 为生产环境修改配置... // 为生产环境修改配置...
if (IS_PROD) { if (IS_PROD) {
// externals // externals
config.externals = externals config.externals = externals
}; }
}, },
chainWebpack: config => { chainWebpack: config => {
// 添加CDN参数到htmlWebpackPlugin配置中 详见public/index.html 修改 /**
* 添加CDN参数到htmlWebpackPlugin配置中
*/
config.plugin('html').tap(args => { config.plugin('html').tap(args => {
if (IS_PROD) { if (IS_PROD) {
// html中添加cdn args[0].cdn = cdn.build
args[0].cdn = cdn } else {
} args[0].cdn = cdn.dev
}
return args return args
}) })
} }
}; }
``` ```
 在 public/index.html 中添加
在 public/index.html 中添加
```javascript ```javascript
<!-- 使用CDN的CSS文件 --> <!-- 使用CDN的CSS文件 -->
<% for (var i in <% for (var i in
htmlWebpackPlugin.options.cdn&&htmlWebpackPlugin.options.cdn.css) { %> htmlWebpackPlugin.options.cdn&&htmlWebpackPlugin.options.cdn.css) { %>
<link href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" rel="preload" as="style" />
<link href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" rel="stylesheet" /> <link href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" rel="stylesheet" />
<% } %> <% } %>
<!-- 使用CDN加速的JS文件配置在vue.config.js下 --> <!-- 使用CDN加速的JS文件配置在vue.config.js下 -->
@ -633,9 +669,12 @@ module.exports = {
### <span id="console">✅ 去掉 console.log </span> ### <span id="console">✅ 去掉 console.log </span>
保留了测试环境和本地环境的 `console.log`
```bash ```bash
npm i -D babel-plugin-transform-remove-console npm i -D babel-plugin-transform-remove-console
``` ```
在 babel.config.js 中配置 在 babel.config.js 中配置
```javascript ```javascript
@ -661,20 +700,83 @@ module.exports = {
presets: [['@vue/cli-plugin-babel/preset', {useBuiltIns: 'entry'}]], presets: [['@vue/cli-plugin-babel/preset', {useBuiltIns: 'entry'}]],
plugins plugins
} }
```
[▲ 回顶部](#top)
### <span id="chunks">✅ splitChunks 单独打包第三方模块</span>
```javascript
module.exports = {
chainWebpack: config => {
config.when(IS_PROD, config => {
config
.plugin('ScriptExtHtmlWebpackPlugin')
.after('html')
.use('script-ext-html-webpack-plugin', [
{
// 将 runtime 作为内联引入不单独存在
inline: /runtime\..*\.js$/
}
])
.end()
config.optimization.splitChunks({
chunks: 'all',
cacheGroups: {
// cacheGroups 下可以可以配置多个组每个组根据test设置条件符合test条件的模块
commons: {
name: 'chunk-commons',
test: resolve('src/components'),
minChunks: 3, // 被至少用三次以上打包分离
priority: 5, // 优先级
reuseExistingChunk: true // 表示是否使用已有的 chunk如果为 true 则表示如果当前的 chunk 包含的模块已经被抽取出去了,那么将不会重新生成新的。
},
node_vendors: {
name: 'chunk-libs',
chunks: 'initial', // 只打包初始时依赖的第三方
test: /[\\/]node_modules[\\/]/,
priority: 10
},
vantUI: {
name: 'chunk-vantUI', // 单独将 vantUI 拆包
priority: 20, // 数字大权重到,满足多个 cacheGroups 的条件时候分到权重高的
test: /[\\/]node_modules[\\/]_?vant(.*)/
}
}
})
config.optimization.runtimeChunk('single')
})
}
}
``` ```
[▲ 回顶部](#top) [▲ 回顶部](#top)
### <span id="ie">✅ 添加 IE 兼容 </span> ### <span id="ie">✅ 添加 IE 兼容 </span>
```bash
npm i -S @babel/polyfill
```
`main.js` 中添加
```javascript
import '@babel/polyfill'
```
配置 `babel.config.js`
```javascript
const plugins = []
module.exports = {
presets: [['@vue/cli-plugin-babel/preset', {useBuiltIns: 'entry'}]],
plugins
}
```
[▲ 回顶部](#top) [▲ 回顶部](#top)
### <span id="console">✅ 去掉 console.log </span>
[▲ 回顶部](#top)
#### 总结 #### 总结
因为项目刚刚构建起来,后面还会持续更新,实际使用过程中一定还有很多问题,如果文章中有错误希望能够被指正,一起成长 因为项目刚刚构建起来,后面还会持续更新,实际使用过程中一定还有很多问题,如果文章中有错误希望能够被指正,一起成长

View File

@ -5,11 +5,11 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<link rel="icon" href="<%= BASE_URL %>favicon.ico"> <link rel="icon" href="<%= BASE_URL %>favicon.ico">
<% for (var i in <!-- <% for (var i in
htmlWebpackPlugin.options.cdn&&htmlWebpackPlugin.options.cdn.css) { %> htmlWebpackPlugin.options.cdn&&htmlWebpackPlugin.options.cdn.css) { %>
<link href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" rel="preload" as="style" /> <link href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" rel="preload" as="style" />
<link href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" rel="stylesheet" /> <link href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" rel="stylesheet" />
<% } %> <% } %> -->
<title><%= webpackConfig.name %></title> <title><%= webpackConfig.name %></title>
</head> </head>
<body> <body>
@ -18,10 +18,10 @@
</noscript> </noscript>
<div id="app"></div> <div id="app"></div>
<!-- 使用CDN加速的JS文件配置在vue.config.js下 --> <!-- 使用CDN加速的JS文件配置在vue.config.js下 -->
<% for (var i in <!-- <% for (var i in
htmlWebpackPlugin.options.cdn&&htmlWebpackPlugin.options.cdn.js) { %> htmlWebpackPlugin.options.cdn&&htmlWebpackPlugin.options.cdn.js) { %>
<script src="<%= htmlWebpackPlugin.options.cdn.js[i] %>"></script> <script src="<%= htmlWebpackPlugin.options.cdn.js[i] %>"></script>
<% } %> <% } %> -->
<!-- built files will be auto injected --> <!-- built files will be auto injected -->
</body> </body>
</html> </html>

View File

@ -4,10 +4,19 @@
<router-view v-if="$route.meta.keepAlive"></router-view> <router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive> </keep-alive>
<router-view v-if="!$route.meta.keepAlive"></router-view> <router-view v-if="!$route.meta.keepAlive"></router-view>
<!-- tabbar -->
<TabBar></TabBar>
</div> </div>
</template> </template>
<script> <script>
import TabBar from '@/components/TabBar'
export default { export default {
name: 'App' name: 'App',
components: {
TabBar
},
} }
</script> </script>
<style lang="scss">
</style>

View File

@ -1,54 +1,5 @@
@import './variables.scss'; @import './variables.scss';
@import './mixin.scss'; @import './mixin.scss';
/* http://meyerweb.com/eric/tools/css/reset/
v2.0 | 20110126
License: none (public domain)
*/
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
body {
line-height: 1;
}
ol, ul {
list-style: none;
}
blockquote, q {
quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content: '';
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
.app-container{ .app-container{
padding-bottom:50px padding-bottom:50px
} }

View File

@ -1,15 +1,22 @@
<template> <template>
<div> <div>
<van-tabbar fixed v-model="active" @change="onChange"> <van-tabbar fixed route>
<van-tabbar-item icon="home-o">首页</van-tabbar-item> <van-tabbar-item to="/" icon="home-o">
<van-tabbar-item icon="good-job-o">github</van-tabbar-item> 首页
</van-tabbar> </van-tabbar-item>
<van-tabbar-item to="/about" icon="user-o">
关于我
</van-tabbar-item>
</van-tabbar>
<!-- <van-tabbar fixed v-model="active" @change="onChange">
<van-tabbar-item to="/home" icon="home-o">首页</van-tabbar-item>
<van-tabbar-item to="/about" icon="user-o">关于我</van-tabbar-item>
</van-tabbar> -->
</div> </div>
</template> </template>
<script> <script>
import _ from 'lodash'
console.log(_.join(['a', 'b'], '~'))
export default { export default {
name: 'TabBar', name: 'TabBar',
data() { data() {
@ -18,9 +25,9 @@ export default {
} }
}, },
methods: { methods: {
onChange(index) { // onChange(index) {
if (index === 1) window.location.href = 'https://github.com/sunniejs/vue-h5-template' // if (index === 1) window.location.href = 'https://github.com/sunniejs/vue-h5-template'
} // }
} }
} }
</script> </script>

View File

@ -4,5 +4,6 @@ module.exports = {
baseUrl: 'http://localhost:9018', // 项目地址 baseUrl: 'http://localhost:9018', // 项目地址
baseApi: 'https://test.xxx.com/api', // 本地api请求地址 baseApi: 'https://test.xxx.com/api', // 本地api请求地址
APPID: 'xxx', APPID: 'xxx',
APPSECRET: 'xxx' APPSECRET: 'xxx',
$cdn:'https://imgs.solui.cn'
} }

View File

@ -4,5 +4,6 @@ module.exports = {
baseUrl: 'https://www.xxx.com/', // 正式项目地址 baseUrl: 'https://www.xxx.com/', // 正式项目地址
baseApi: 'https://www.xxx.com/api', // 正式api请求地址 baseApi: 'https://www.xxx.com/api', // 正式api请求地址
APPID: 'xxx', APPID: 'xxx',
APPSECRET: 'xxx' APPSECRET: 'xxx',
$cdn:'https://imgs.solui.cn'
} }

View File

@ -3,5 +3,6 @@ module.exports = {
baseUrl: 'https://test.xxx.com', // 测试项目地址 baseUrl: 'https://test.xxx.com', // 测试项目地址
baseApi: 'https://test.xxx.com/api', // 测试api请求地址 baseApi: 'https://test.xxx.com/api', // 测试api请求地址
APPID: 'xxx', APPID: 'xxx',
APPSECRET: 'xxx' APPSECRET: 'xxx',
$cdn:'https://imgs.solui.cn'
} }

View File

@ -5,7 +5,7 @@ import App from './App.vue'
import router from './router' import router from './router'
import store from './store' import store from './store'
// 引入全局样式 // 引入全局样式
import '@/assets/css/index.scss' // import '@/assets/css/index.scss'
// 全局引入按需引入UI库 vant // 全局引入按需引入UI库 vant
import '@/plugins/vant' import '@/plugins/vant'

View File

@ -6,45 +6,31 @@
<h2 class="demo-home__desc"> <h2 class="demo-home__desc">
A vue h5 template with Vant UI A vue h5 template with Vant UI
</h2> </h2>
<div class="list">
<div class="item">项目地址: <a href="https://github.com/sunniejs">https://github.com/sunniejs</a></div>
<div class="item">项目作者: sunnie</div>
<div class="item"></div>
<div class="author"></div>
</div>
</div> </div>
<van-cell icon="success" v-for="item in list" :key="item" :title="item" />
<!-- tabbar -->
<TabBar></TabBar>
</div> </div>
</template> </template>
<script> <script>
import TabBar from '@/components/TabBar'
// //
import {getUserInfo} from '@/api/user.js' import { getUserInfo } from '@/api/user.js'
export default { export default {
components: {
TabBar
},
data() { data() {
return { return {
list: [
'Vue-cli4',
'VantUI组件按需加载',
'Sass',
'Webpack 4',
'Vue-router',
'Vuex',
'Axios封装',
'rem适配方案',
'多环境配置',
'生产环境cdn优化首屏加速',
'babel低版本浏览器兼容',
'Eslint+Pettier统一开发规范'
]
} }
}, },
computed: {}, computed: {},
mounted() { mounted() {
this.initData() this.initData()
}, },
@ -52,10 +38,10 @@ export default {
// //
initData() { initData() {
// src->config // src->config
const params = {user: 'sunnie'} const params = { user: 'sunnie' }
getUserInfo(params) getUserInfo(params)
.then(() => {}) .then(() => { })
.catch(() => {}) .catch(() => { })
} }
} }
} }
@ -64,6 +50,7 @@ export default {
.app-container { .app-container {
.warpper { .warpper {
padding: 12px; padding: 12px;
background: $background-color;
.demo-home__title { .demo-home__title {
margin: 0 0 6px; margin: 0 0 6px;
font-size: 32px; font-size: 32px;
@ -85,6 +72,23 @@ export default {
color: rgba(69, 90, 100, 0.6); color: rgba(69, 90, 100, 0.6);
font-size: 14px; font-size: 14px;
} }
.list {
display: flex;
flex-direction: column;
color: #666;
font-size: 14px;
.item {
font-size: 14px;
line-height: 24px;
}
}
.author {
margin:10px auto;
width: 200px;
height: 200px;
background: url($cdn+'/weapp/me.png') center / contain no-repeat;
}
} }
} }
</style> </style>

View File

@ -8,36 +8,35 @@
</h2> </h2>
</div> </div>
<van-cell icon="success" v-for="item in list" :key="item" :title="item" /> <van-cell icon="success" v-for="item in list" :key="item" :title="item" />
<!-- tabbar -->
<TabBar></TabBar>
</div> </div>
</template> </template>
<script> <script>
import TabBar from '@/components/TabBar' import TabBar from '@/components/TabBar'
// //
import {getUserInfo} from '@/api/user.js' import { getUserInfo } from '@/api/user.js'
export default { export default {
components: {
TabBar
},
data() { data() {
return { return {
list: [ list: [
'Vue-cli4', 'Vue-cli4',
'VantUI组件按需加载', ' 配置多环境变量',
'Sass', ' VantUI 组件按需加载',
' Sass',
'Webpack 4', 'Webpack 4',
'Vue-router',
'Vuex', 'Vuex',
'Axios封装', ' Axios 封装及接口管理',
'rem适配方案', 'Vue-router',
'多环境配置', 'vue.config.js 基础配置',
'生产环境cdn优化首屏加速', '配置 proxy 跨域',
'babel低版本浏览器兼容', '配置 alias 别名',
'Eslint+Pettier统一开发规范' '配置 打包分析',
'配置 externals 引入 cdn 资源',
'去掉 console.log',
'splitChunks 单独打包第三方模块',
' 添加 IE 兼容'
] ]
} }
}, },
@ -52,19 +51,19 @@ export default {
// //
initData() { initData() {
// src->config // src->config
const params = {user: 'sunnie'} const params = { user: 'sunnie' }
getUserInfo(params) getUserInfo(params)
.then(() => {}) .then(() => { })
.catch(() => {}) .catch(() => { })
} }
} }
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
// @import '@/assets/css/index.scss';
.app-container { .app-container {
.warpper { .warpper {
padding: 12px; padding: 12px;
background: $background-color;
.demo-home__title { .demo-home__title {
margin: 0 0 6px; margin: 0 0 6px;
font-size: 32px; font-size: 32px;

View File

@ -9,44 +9,31 @@ const name = defaultSettings.title || 'vue mobile template'
const IS_PROD = ['production', 'prod'].includes(process.env.NODE_ENV) const IS_PROD = ['production', 'prod'].includes(process.env.NODE_ENV)
// externals // externals
const externals = { // const externals = {
vue: 'Vue', // vue: 'Vue',
'vue-router': 'VueRouter', // 'vue-router': 'VueRouter',
vuex: 'Vuex', // vuex: 'Vuex',
vant: 'vant', // vant: 'vant',
axios: 'axios' // axios: 'axios'
} // }
// CDN外链会插入到index.html中 // CDN外链会插入到index.html中
const cdn = {
// 开发环境
dev: {
css: [
],
js: []
},
// 生产环境
build: {
css: ['https://cdn.jsdelivr.net/npm/vant@2.4.7/lib/index.css'],
js: [
'https://cdn.jsdelivr.net/npm/vue@2.6.11/dist/vue.min.js',
'https://cdn.jsdelivr.net/npm/vue-router@3.1.5/dist/vue-router.min.js',
'https://cdn.jsdelivr.net/npm/axios@0.19.2/dist/axios.min.js',
'https://cdn.jsdelivr.net/npm/vuex@3.1.2/dist/vuex.min.js',
'https://cdn.jsdelivr.net/npm/vant@2.4.7/lib/index.min.js'
]
}
}
// const cdn = { // const cdn = {
// css: ['https://cdn.jsdelivr.net/npm/vant@2.4.7/lib/index.css'], // // 开发环境
// js: [ // dev: {
// 'https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.min.js', // css: [],
// 'https://cdnjs.cloudflare.com/ajax/libs/vue-router/3.1.5/vue-router.min.js', // js: []
// 'https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.2/axios.min.js', // },
// 'https://cdnjs.cloudflare.com/ajax/libs/vuex/3.1.2/vuex.min.js', // // 生产环境
// 'https://cdn.jsdelivr.net/npm/vant@2.4.7/lib/index.min.js', // build: {
// 'https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/crypto-js.min.js', // css: ['https://cdn.jsdelivr.net/npm/vant@2.4.7/lib/index.css'],
// js: [
// ] // 'https://cdn.jsdelivr.net/npm/vue@2.6.11/dist/vue.min.js',
// 'https://cdn.jsdelivr.net/npm/vue-router@3.1.5/dist/vue-router.min.js',
// 'https://cdn.jsdelivr.net/npm/axios@0.19.2/dist/axios.min.js',
// 'https://cdn.jsdelivr.net/npm/vuex@3.1.2/dist/vuex.min.js',
// 'https://cdn.jsdelivr.net/npm/vant@2.4.7/lib/index.min.js'
// ]
// }
// } // }
module.exports = { module.exports = {
@ -55,7 +42,7 @@ module.exports = {
outputDir: 'dist', // 生产环境构建文件的目录 outputDir: 'dist', // 生产环境构建文件的目录
assetsDir: 'static', // outputDir的静态资源(js、css、img、fonts)目录 assetsDir: 'static', // outputDir的静态资源(js、css、img、fonts)目录
lintOnSave: false, lintOnSave: false,
productionSourceMap: !IS_PROD, // 生产环境的 source map productionSourceMap: false, // 如果你不需要生产环境的 source map可以将其设置为 false 以加速生产环境构建。
devServer: { devServer: {
port: 9020, // 端口 port: 9020, // 端口
open: false, // 启动后打开浏览器 open: false, // 启动后打开浏览器
@ -76,16 +63,27 @@ module.exports = {
// } // }
// } // }
}, },
css: {
extract: IS_PROD,
sourceMap: false,
loaderOptions: {
scss: {
// 向全局sass样式传入共享的全局变量, $src可以配置图片cdn前缀
// 详情: https://cli.vuejs.org/guide/css.html#passing-options-to-pre-processor-loaders
prependData: `
@import "assets/css/index.scss";
$cdn: "${defaultSettings.$cdn}";
`
}
}
},
configureWebpack: config => { configureWebpack: config => {
config.name = name config.name = name
// 为生产环境修改配置... // 为生产环境修改配置...
if (IS_PROD) { // if (IS_PROD) {
// externals // // externals
config.externals = externals // config.externals = externals
}
// 为开发环境修改配置...
// if (process.env.NODE_ENV === 'development') {
// } // }
}, },
@ -100,7 +98,34 @@ module.exports = {
.set('api', resolve('src/api')) .set('api', resolve('src/api'))
.set('views', resolve('src/views')) .set('views', resolve('src/views'))
.set('components', resolve('src/components')) .set('components', resolve('src/components'))
// 打包分析
/**
* 添加CDN参数到htmlWebpackPlugin配置中
*/
// config.plugin('html').tap(args => {
// if (IS_PROD) {
// args[0].cdn = cdn.build
// } else {
// args[0].cdn = cdn.dev
// }
// return args
// })
/**
* 设置保留空格
*/
config.module
.rule('vue')
.use('vue-loader')
.loader('vue-loader')
.tap(options => {
options.compilerOptions.preserveWhitespace = true
return options
})
.end()
/**
* 打包分析
*/
if (IS_PROD) { if (IS_PROD) {
config.plugin('webpack-report').use(BundleAnalyzerPlugin, [ config.plugin('webpack-report').use(BundleAnalyzerPlugin, [
{ {
@ -108,69 +133,46 @@ module.exports = {
} }
]) ])
} }
/** config
* 添加CDN参数到htmlWebpackPlugin配置中 // https://webpack.js.org/configuration/devtool/#development
*/ .when(!IS_PROD, config => config.devtool('cheap-source-map'))
config.plugin('html').tap(args => {
if (IS_PROD) {
args[0].cdn = cdn.build
} else {
args[0].cdn = cdn.dev
}
return args config.when(IS_PROD, config => {
}) config
// set preserveWhitespace .plugin('ScriptExtHtmlWebpackPlugin')
// config.module .after('html')
// .rule('vue') .use('script-ext-html-webpack-plugin', [
// .use('vue-loader') {
// .loader('vue-loader') // 将 runtime 作为内联引入不单独存在
// .tap(options => { inline: /runtime\..*\.js$/
// options.compilerOptions.preserveWhitespace = true }
// return options ])
// }) .end()
// .end() config.optimization.splitChunks({
chunks: 'all',
// config cacheGroups: {
// // https://webpack.js.org/configuration/devtool/#development // cacheGroups 下可以可以配置多个组每个组根据test设置条件符合test条件的模块
// .when(process.env.NODE_ENV === 'development', config => config.devtool('cheap-source-map')) commons: {
name: 'chunk-commons',
// config.when(IS_PROD, config => { test: resolve('src/components'),
// config minChunks: 3, // 被至少用三次以上打包分离
// .plugin('ScriptExtHtmlWebpackPlugin') priority: 5, // 优先级
// .after('html') reuseExistingChunk: true // 表示是否使用已有的 chunk如果为 true 则表示如果当前的 chunk 包含的模块已经被抽取出去了,那么将不会重新生成新的。
// .use('script-ext-html-webpack-plugin', [ },
// { node_vendors: {
// // `runtime` must same as runtimeChunk name. default is `runtime` name: 'chunk-libs',
// inline: /runtime\..*\.js$/ chunks: 'initial', // 只打包初始时依赖的第三方
// } test: /[\\/]node_modules[\\/]/,
// ]) priority: 10
// .end() },
// config.optimization.splitChunks({ vantUI: {
// chunks: 'all', name: 'chunk-vantUI', // 单独将 vantUI 拆包
// cacheGroups: { priority: 20, // 数字大权重到,满足多个 cacheGroups 的条件时候分到权重高的
// // cacheGroups 下可以可以配置多个组每个组根据test设置条件符合test条件的模块 test: /[\\/]node_modules[\\/]_?vant(.*)/
// commons: { }
// name: 'chunk-commons', }
// test: resolve('src/components'), })
// minChunks: 3, // 被至少用三次以上打包分离 config.optimization.runtimeChunk('single')
// priority: 5, // 优先级 })
// reuseExistingChunk: true // 复用其他chunk内已拥有的模块
// },
// // vantUI: {
// // name: 'chunk-vantUI', // 将 vant 打包到单独文件
// // priority: 20,
// // test: /[\\/]node_modules[\\/]_?vant(.*)/ // in order to adapt to cnpm
// // },
// libs: {
// name: 'chunk-libs',
// chunks: 'initial', // only package third parties that are initially dependent
// test: /[\\/]node_modules[\\/]/,
// priority: 10
// }
// }
// })
// config.optimization.runtimeChunk('single')
// })
} }
} }