452ad3d7 by 宋楠

dev

1 parent 4b1a42fb
......@@ -25,8 +25,14 @@
- [√ Axios 封装及接口管理](#axios)
- [√ Vue-router](#router)
- [√ vue.config.js 基础配置](#base)
- [√ vue.config.js 配置 proxy 跨域](#proxy)
- [√ vue.config.js 配置 proxy 跨域](#proxy)
- [√ 配置 proxy 跨域](#proxy)
- [√ 配置 alias 别名](#alias)
- [√ 配置 打包分析](#bundle)
- [√ 配置 externals 引入 cdn 资源 ](#externals)
- [√ 去掉 console.log ](#console)
- [√ splitChunks ](#console)
- [√ 添加 IE 兼容 ](#ie)
* Vuex
* Axios 封装
......@@ -476,7 +482,7 @@ module.exports = {
[▲ 回顶部](#top)
### <span id="proxy">✅ vue.config.js 配置 proxy 跨域 </span>
### <span id="proxy">✅ 配置 proxy 跨域 </span>
如果你的项目需要跨域设置,你需要打来 `vue.config.js` `proxy` 注释 并且配置相应参数
......@@ -515,10 +521,160 @@ export function getUserInfo(params) {
[▲ 回顶部](#top)
### <span id="proxy">✅ vue.config.js 配置 proxy 跨域 </span>
### <span id="alias">✅ 配置 alias 别名 </span>
```javascript
const path = require("path");
const resolve = dir => path.join(__dirname, dir);
const IS_PROD = ["production", "prod"].includes(process.env.NODE_ENV);
module.exports = {
chainWebpack: config => {
// 添加别名
config.resolve.alias
.set('@', resolve('src'))
.set('assets', resolve('src/assets'))
.set('api', resolve('src/api'))
.set('views', resolve('src/views'))
.set('components', resolve('src/components'))
}
};
```
[▲ 回顶部](#top)
### <span id="bundle">✅ 配置 打包分析 </span>
```javascript
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer")
.BundleAnalyzerPlugin;
module.exports = {
chainWebpack: config => {
// 打包分析
if (IS_PROD) {
config.plugin("webpack-report").use(BundleAnalyzerPlugin, [
{
analyzerMode: "static"
}
]);
}
}
};
```
```bash
npm run build
```
[▲ 回顶部](#top)
### <span id="proxy">✅ 配置 externals 引入 cdn 资源 </span>
```javascript
const defaultSettings = require('./src/config/index.js')
const name = defaultSettings.title || 'vue mobile template'
const IS_PROD = ["production", "prod"].includes(process.env.NODE_ENV);
// externals
const externals = {
vue: 'Vue',
'vue-router': 'VueRouter',
vuex: 'Vuex',
vant: 'vant',
axios: 'axios'
}
// cdn
const cdn = {
css: ['https://cdn.jsdelivr.net/npm/vant@beta/lib/index.css'],
js: [
'https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js',
'https://cdnjs.cloudflare.com/ajax/libs/vue-router/3.0.6/vue-router.min.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',
'https://cdn.jsdelivr.net/npm/vant@beta/lib/vant.min.js'
]
}
module.exports = {
configureWebpack: config => {
config.name = name
// 为生产环境修改配置...
if (IS_PROD) {
// externals
config.externals = externals
};
},
chainWebpack: config => {
// 添加CDN参数到htmlWebpackPlugin配置中, 详见public/index.html 修改
config.plugin('html').tap(args => {
if (IS_PROD) {
// html中添加cdn
args[0].cdn = cdn
}
return args
})
}
};
```
 在 public/index.html 中添加
```javascript
<!-- 使用CDNCSS文件 -->
<% for (var i in
htmlWebpackPlugin.options.cdn&&htmlWebpackPlugin.options.cdn.css) { %>
<link href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" rel="stylesheet" />
<% } %>
<!-- 使用CDN加速的JS文件,配置在vue.config.js -->
<% for (var i in
htmlWebpackPlugin.options.cdn&&htmlWebpackPlugin.options.cdn.js) { %>
<script src="<%= htmlWebpackPlugin.options.cdn.js[i] %>"></script>
<% } %>
```
[▲ 回顶部](#top)
### <span id="console">✅ 去掉 console.log </span>
```bash
npm i -D babel-plugin-transform-remove-console
```
在 babel.config.js 中配置
```javascript
// 获取 VUE_APP_ENV 非 NODE_ENV,测试环境依然 console
const IS_PROD = ['production', 'prod'].includes(process.env.VUE_APP_ENV)
const plugins = [
[
'import',
{
libraryName: 'vant',
libraryDirectory: 'es',
style: true
},
'vant'
]
]
// 去除 console.log
if (IS_PROD) {
plugins.push('transform-remove-console')
}
module.exports = {
presets: [['@vue/cli-plugin-babel/preset', {useBuiltIns: 'entry'}]],
plugins
}
```
[▲ 回顶部](#top)
### <span id="ie">✅ 添加 IE 兼容 </span>
[▲ 回顶部](#top)
### <span id="console">✅ 去掉 console.log </span>
[▲ 回顶部](#top)
#### 总结
因为项目刚刚构建起来,后面还会持续更新,实际使用过程中一定还有很多问题,如果文章中有错误希望能够被指正,一起成长
......
module.exports = {
presets: [['@vue/cli-plugin-babel/preset', {useBuiltIns: 'entry'}]],
plugins: [
// 获取 VUE_APP_ENV 非 NODE_ENV,测试环境依然 console
const IS_PROD = ['production', 'prod'].includes(process.env.VUE_APP_ENV)
const plugins = [
[
'import',
{
......@@ -10,5 +10,13 @@ module.exports = {
},
'vant'
]
]
]
// 去除 console.log
if (IS_PROD) {
plugins.push('transform-remove-console')
}
module.exports = {
presets: [['@vue/cli-plugin-babel/preset', {useBuiltIns: 'entry'}]],
plugins
}
......
This diff could not be displayed because it is too large.
......@@ -14,6 +14,7 @@
"axios": "^0.19.2",
"core-js": "^3.6.4",
"lib-flexible": "^0.3.2",
"lodash": "^4.17.15",
"vant": "^2.4.7",
"vue": "^2.6.11",
"vue-router": "^3.1.5",
......@@ -36,6 +37,7 @@
"prettier": "^1.19.1",
"sass-loader": "^8.0.2",
"script-ext-html-webpack-plugin": "^2.1.4",
"vue-template-compiler": "^2.6.11"
"vue-template-compiler": "^2.6.11",
"webpack-bundle-analyzer": "^3.7.0"
}
}
......
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<p>
For a guide and recipes on how to configure / customize this project,<br />
check out the
<a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
</p>
<h3>Installed CLI Plugins</h3>
<ul>
<li>
<a
href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel"
target="_blank"
rel="noopener"
>babel</a
>
</li>
<li>
<a
href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint"
target="_blank"
rel="noopener"
>eslint</a
>
</li>
</ul>
<h3>Essential Links</h3>
<ul>
<li>
<a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a>
</li>
<li>
<a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a>
</li>
<li>
<a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a>
</li>
<li>
<a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a>
</li>
<li>
<a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a>
</li>
</ul>
<h3>Ecosystem</h3>
<ul>
<li>
<a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a>
</li>
<li>
<a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a>
</li>
<li>
<a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a>
</li>
<li>
<a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a>
</li>
<li>
<a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a>
</li>
</ul>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
msg: String
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
<template>
<div>
<van-tabbar fixed v-model="active" @change="onChange">
<van-tabbar-item icon="home-o">首页</van-tabbar-item>
<van-tabbar-item icon="good-job-o">github</van-tabbar-item>
</van-tabbar>
</div>
</template>
<script>
import _ from 'lodash'
console.log(_.join(['a', 'b'], '~'))
export default {
name: 'TabBar',
data() {
return {
active: 0
}
},
methods: {
onChange(index) {
if (index === 1) window.location.href = 'https://github.com/sunniejs/vue-h5-template'
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
......@@ -11,6 +11,15 @@ export const router = [
title: '首页', // 页面标题
keepAlive: false // keep-alive 标识
}
},
{
path: '/about',
name: 'about',
component: () => import('@/views/home/about'),
meta: {
title: '关于我',
keepAlive: false
}
}
]
......
<!-- home -->
<template>
<div class="app-container">
<div class="warpper">
<h1 class="demo-home__title"><img src="https://imgs.solui.cn/weapp/logo.png" /><span>VUE H5开发模板</span></h1>
<h2 class="demo-home__desc">
A vue h5 template with Vant UI
</h2>
</div>
<van-cell icon="success" v-for="item in list" :key="item" :title="item" />
<!-- tabbar -->
<TabBar></TabBar>
</div>
</template>
<script>
import TabBar from '@/components/TabBar'
// 请求接口
import {getUserInfo} from '@/api/user.js'
export default {
components: {
TabBar
},
data() {
return {
list: [
'Vue-cli4',
'VantUI组件按需加载',
'Sass',
'Webpack 4',
'Vue-router',
'Vuex',
'Axios封装',
'rem适配方案',
'多环境配置',
'生产环境cdn优化首屏加速',
'babel低版本浏览器兼容',
'Eslint+Pettier统一开发规范'
]
}
},
computed: {},
mounted() {
this.initData()
},
methods: {
// 请求数据案例
initData() {
// 请求接口数据,仅作为展示,需要配置src->config下环境文件
const params = {user: 'sunnie'}
getUserInfo(params)
.then(() => {})
.catch(() => {})
}
}
}
</script>
<style lang="scss" scoped>
.app-container {
.warpper {
padding: 12px;
.demo-home__title {
margin: 0 0 6px;
font-size: 32px;
.demo-home__title img,
.demo-home__title span {
display: inline-block;
vertical-align: middle;
}
img {
width: 32px;
}
span {
margin-left: 16px;
font-weight: 500;
}
}
.demo-home__desc {
margin: 0 0 20px;
color: rgba(69, 90, 100, 0.6);
font-size: 14px;
}
}
}
</style>
......@@ -8,22 +8,23 @@
</h2>
</div>
<van-cell icon="success" v-for="item in list" :key="item" :title="item" />
<van-tabbar fixed v-model="active" @change="onChange">
<van-tabbar-item icon="home-o">首页</van-tabbar-item>
<van-tabbar-item icon="good-job-o">github</van-tabbar-item>
</van-tabbar>
<!-- tabbar -->
<TabBar></TabBar>
</div>
</template>
<script>
import TabBar from '@/components/TabBar'
// 请求接口
import { getUserInfo } from '@/api/user.js'
import {getUserInfo} from '@/api/user.js'
export default {
components: {},
components: {
TabBar
},
data() {
return {
active: 0,
list: [
'Vue-cli4',
'VantUI组件按需加载',
......@@ -51,18 +52,16 @@ export default {
// 请求数据案例
initData() {
// 请求接口数据,仅作为展示,需要配置src->config下环境文件
const params = {user:'sunnie'}
getUserInfo()
.then(() => { })
.catch(() => { })
},
onChange(index) {
if (index === 1) window.location.href = 'https://github.com/sunnie1992/vue-h5-template'
const params = {user: 'sunnie'}
getUserInfo(params)
.then(() => {})
.catch(() => {})
}
}
}
</script>
<style lang="scss" scoped>
// @import '@/assets/css/index.scss';
.app-container {
.warpper {
padding: 12px;
......
'use strict'
const path = require('path')
const defaultSettings = require('./src/config/index.js')
function resolve(dir) {
return path.join(__dirname, dir)
}
const name = defaultSettings.title || 'vue mobile template' // page title
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
const resolve = dir => path.join(__dirname, dir)
// page title
const name = defaultSettings.title || 'vue mobile template'
const IS_PROD = ['production', 'prod'].includes(process.env.NODE_ENV)
// externals
const externals = {
vue: 'Vue',
'vue-router': 'VueRouter',
......@@ -13,27 +16,39 @@ const externals = {
vant: 'vant',
axios: 'axios'
}
// cdn
// CDN外链,会插入到index.html中
const cdn = {
// 开发环境
dev: {
css: [],
css: [
],
js: []
},
// 生产环境
build: {
css: ['https://cdn.jsdelivr.net/npm/vant@beta/lib/index.css'],
css: ['https://cdn.jsdelivr.net/npm/vant@2.4.7/lib/index.css'],
js: [
'https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js',
'https://cdnjs.cloudflare.com/ajax/libs/vue-router/3.0.6/vue-router.min.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',
'https://cdn.jsdelivr.net/npm/vant@beta/lib/vant.min.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 IS_PROD = ['production', 'prod'].includes(process.env.NODE_ENV)
// const cdn = {
// css: ['https://cdn.jsdelivr.net/npm/vant@2.4.7/lib/index.css'],
// js: [
// 'https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.min.js',
// 'https://cdnjs.cloudflare.com/ajax/libs/vue-router/3.1.5/vue-router.min.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',
// 'https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/crypto-js.min.js',
// ]
// }
module.exports = {
publicPath: './', // 署应用包时的基本 URL。 vue-router hash 模式使用
// publicPath: '/app/', //署应用包时的基本 URL。 vue-router history模式使用
......@@ -48,7 +63,7 @@ module.exports = {
// 当出现编译器错误或警告时,在浏览器中显示全屏覆盖层
warnings: false,
errors: true
},
}
// proxy: {
// //配置跨域
// '/api': {
......@@ -63,87 +78,99 @@ module.exports = {
},
configureWebpack: config => {
config.name = name
// 为生产环境修改配置...
if (process.env.NODE_ENV === 'production') {
// externals里的模块不打包
Object.assign(config, {
name: name,
externals: externals
})
if (IS_PROD) {
// externals
config.externals = externals
}
// 为开发环境修改配置...
// if (process.env.NODE_ENV === 'development') {
// }
},
chainWebpack(config) {
chainWebpack: config => {
config.plugins.delete('preload') // TODO: need test
config.plugins.delete('prefetch') // TODO: need test
// alias
// 别名 alias
config.resolve.alias
.set('@', resolve('src'))
.set('assets', resolve('src/assets'))
.set('api', resolve('src/api'))
.set('views', resolve('src/views'))
.set('components', resolve('src/components'))
// 打包分析
if (IS_PROD) {
config.plugin('webpack-report').use(BundleAnalyzerPlugin, [
{
analyzerMode: 'static'
}
])
}
/**
* 添加CDN参数到htmlWebpackPlugin配置中, 详见public/index.html 修改
* 添加CDN参数到htmlWebpackPlugin配置中
*/
config.plugin('html').tap(args => {
if (process.env.NODE_ENV === 'production') {
if (IS_PROD) {
args[0].cdn = cdn.build
}
if (process.env.NODE_ENV === 'development') {
} else {
args[0].cdn = cdn.dev
}
return args
})
// set preserveWhitespace
config.module
.rule('vue')
.use('vue-loader')
.loader('vue-loader')
.tap(options => {
options.compilerOptions.preserveWhitespace = true
return options
})
.end()
// config.module
// .rule('vue')
// .use('vue-loader')
// .loader('vue-loader')
// .tap(options => {
// options.compilerOptions.preserveWhitespace = true
// return options
// })
// .end()
config
// https://webpack.js.org/configuration/devtool/#development
.when(process.env.NODE_ENV === 'development', config => config.devtool('cheap-source-map'))
// config
// // https://webpack.js.org/configuration/devtool/#development
// .when(process.env.NODE_ENV === 'development', config => config.devtool('cheap-source-map'))
config.when(process.env.NODE_ENV !== 'development', config => {
config
.plugin('ScriptExtHtmlWebpackPlugin')
.after('html')
.use('script-ext-html-webpack-plugin', [
{
// `runtime` must same as runtimeChunk name. default is `runtime`
inline: /runtime\..*\.js$/
}
])
.end()
config.optimization.splitChunks({
chunks: 'all',
cacheGroups: {
commons: {
name: 'chunk-commons',
test: resolve('src/components'), // can customize your rules
minChunks: 3, // minimum common number
priority: 5,
reuseExistingChunk: true
},
libs: {
name: 'chunk-libs',
chunks: 'initial', // only package third parties that are initially dependent
test: /[\\/]node_modules[\\/]/,
priority: 10
}
}
})
config.optimization.runtimeChunk('single')
})
// config.when(IS_PROD, config => {
// config
// .plugin('ScriptExtHtmlWebpackPlugin')
// .after('html')
// .use('script-ext-html-webpack-plugin', [
// {
// // `runtime` must same as runtimeChunk name. default is `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内已拥有的模块
// },
// // 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')
// })
}
}
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!