6c4a6a6f by sunnie

about

1 parent 452ad3d7
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
2 2
3 基于 vue-cli3.0+webpack 4+vant ui + sass+ rem 适配方案+axios 封装,构建手机端模板脚手架 3 基于 vue-cli3.0+webpack 4+vant ui + sass+ rem 适配方案+axios 封装,构建手机端模板脚手架
4 4
5 [关于项目介绍](https://juejin.im/post/5cfefc73f265da1bba58f9f7) 5 掘金: [vue-cli4 vant rem 移动端框架方案](https://juejin.im/post/5cfefc73f265da1bba58f9f7)
6 6
7 [demo](https://solui.cn/vue-h5-template/#/)建议手机端查看 7 [demo](https://solui.cn/vue-h5-template/#/)建议手机端查看
8 8
...@@ -13,6 +13,19 @@ ...@@ -13,6 +13,19 @@
13 13
14 本示例 Node.js 12.14.1 14 本示例 Node.js 12.14.1
15 15
16 ### 启动项目
17
18 ```bash
19
20 git clone https://github.com/sunniejs/vue-h5-template.git
21
22 cd vue-h5-template
23
24 npm install
25
26 npm run serve
27 ```
28
16 <span id="top">目录</span> 29 <span id="top">目录</span>
17 30
18 - [√ Vue-cli4](https://cli.vuejs.org/zh/guide/) 31 - [√ Vue-cli4](https://cli.vuejs.org/zh/guide/)
...@@ -30,10 +43,9 @@ ...@@ -30,10 +43,9 @@
30 - [√ 配置 打包分析](#bundle) 43 - [√ 配置 打包分析](#bundle)
31 - [√ 配置 externals 引入 cdn 资源 ](#externals) 44 - [√ 配置 externals 引入 cdn 资源 ](#externals)
32 - [√ 去掉 console.log ](#console) 45 - [√ 去掉 console.log ](#console)
33 - [√ splitChunks ](#console) 46 - [√ splitChunks 单独打包第三方模块](#chunks)
34 - [√ 添加 IE 兼容 ](#ie) 47 - [√ 添加 IE 兼容 ](#ie)
35 48
36
37 * Vuex 49 * Vuex
38 * Axios 封装 50 * Axios 封装
39 * 生产环境 cdn 优化首屏加速 51 * 生产环境 cdn 优化首屏加速
...@@ -466,7 +478,7 @@ module.exports = { ...@@ -466,7 +478,7 @@ module.exports = {
466 outputDir: 'dist', // 生产环境构建文件的目录 478 outputDir: 'dist', // 生产环境构建文件的目录
467 assetsDir: 'static', // outputDir的静态资源(js、css、img、fonts)目录 479 assetsDir: 'static', // outputDir的静态资源(js、css、img、fonts)目录
468 lintOnSave: false, 480 lintOnSave: false,
469 productionSourceMap: !IS_PROD, // 生产环境的 source map 481 productionSourceMap: false, // 如果你不需要生产环境的 source map,可以将其设置为 false 以加速生产环境构建。
470 devServer: { 482 devServer: {
471 port: 9020, // 端口号 483 port: 9020, // 端口号
472 open: false, // 启动后打开浏览器 484 open: false, // 启动后打开浏览器
...@@ -524,9 +536,9 @@ export function getUserInfo(params) { ...@@ -524,9 +536,9 @@ export function getUserInfo(params) {
524 ### <span id="alias">✅ 配置 alias 别名 </span> 536 ### <span id="alias">✅ 配置 alias 别名 </span>
525 537
526 ```javascript 538 ```javascript
527 const path = require("path"); 539 const path = require('path')
528 const resolve = dir => path.join(__dirname, dir); 540 const resolve = dir => path.join(__dirname, dir)
529 const IS_PROD = ["production", "prod"].includes(process.env.NODE_ENV); 541 const IS_PROD = ['production', 'prod'].includes(process.env.NODE_ENV)
530 542
531 module.exports = { 543 module.exports = {
532 chainWebpack: config => { 544 chainWebpack: config => {
...@@ -538,40 +550,52 @@ module.exports = { ...@@ -538,40 +550,52 @@ module.exports = {
538 .set('views', resolve('src/views')) 550 .set('views', resolve('src/views'))
539 .set('components', resolve('src/components')) 551 .set('components', resolve('src/components'))
540 } 552 }
541 }; 553 }
542 ``` 554 ```
555
543 [▲ 回顶部](#top) 556 [▲ 回顶部](#top)
544 557
545 ### <span id="bundle">✅ 配置 打包分析 </span> 558 ### <span id="bundle">✅ 配置 打包分析 </span>
546 559
547 ```javascript 560 ```javascript
548 const BundleAnalyzerPlugin = require("webpack-bundle-analyzer") 561 const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
549 .BundleAnalyzerPlugin;
550 562
551 module.exports = { 563 module.exports = {
552 chainWebpack: config => { 564 chainWebpack: config => {
553 // 打包分析 565 // 打包分析
554 if (IS_PROD) { 566 if (IS_PROD) {
555 config.plugin("webpack-report").use(BundleAnalyzerPlugin, [ 567 config.plugin('webpack-report').use(BundleAnalyzerPlugin, [
556 { 568 {
557 analyzerMode: "static" 569 analyzerMode: 'static'
558 } 570 }
559 ]); 571 ])
560 } 572 }
561 } 573 }
562 }; 574 }
563 ``` 575 ```
576
564 ```bash 577 ```bash
565 npm run build 578 npm run build
566 ``` 579 ```
580
567 [▲ 回顶部](#top) 581 [▲ 回顶部](#top)
568 582
569 ### <span id="proxy">✅ 配置 externals 引入 cdn 资源 </span> 583 ### <span id="proxy">✅ 配置 externals 引入 cdn 资源 </span>
570 584
585 这个版本 CDN 不再引入,我测试了一下使用引入 CDN 和不使用,不使用会比使用时间少。网上不少文章测试 CDN 速度块,这个开发者可
586 以实际测试一下。
587
588 另外项目中使用的是公共 CDN 不稳定,域名解析也是需要时间的(如果你要使用请尽量使用同一个域名)
589
590 因为页面每次遇到`<script>`标签都会停下来解析执行,所以应该尽可能减少`<script>`标签的数量 `HTTP`请求存在一定的开销,100K
591 的文件比 5 个 20K 的文件下载的更快,所以较少脚本数量也是很有必要的
592
593 暂时还没有研究放到自己的 cdn 服务器上。
594
571 ```javascript 595 ```javascript
572 const defaultSettings = require('./src/config/index.js') 596 const defaultSettings = require('./src/config/index.js')
573 const name = defaultSettings.title || 'vue mobile template' 597 const name = defaultSettings.title || 'vue mobile template'
574 const IS_PROD = ["production", "prod"].includes(process.env.NODE_ENV); 598 const IS_PROD = ['production', 'prod'].includes(process.env.NODE_ENV)
575 599
576 // externals 600 // externals
577 const externals = { 601 const externals = {
...@@ -581,45 +605,57 @@ const externals = { ...@@ -581,45 +605,57 @@ const externals = {
581 vant: 'vant', 605 vant: 'vant',
582 axios: 'axios' 606 axios: 'axios'
583 } 607 }
584 // cdn 608 // CDN外链,会插入到index.html中
585 const cdn = { 609 const cdn = {
586 css: ['https://cdn.jsdelivr.net/npm/vant@beta/lib/index.css'], 610 // 开发环境
587 js: [ 611 dev: {
588 'https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js', 612 css: [],
589 'https://cdnjs.cloudflare.com/ajax/libs/vue-router/3.0.6/vue-router.min.js', 613 js: []
590 'https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.min.js', 614 },
591 'https://cdnjs.cloudflare.com/ajax/libs/vuex/3.1.1/vuex.min.js', 615 // 生产环境
592 'https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/crypto-js.min.js', 616 build: {
593 'https://cdn.jsdelivr.net/npm/vant@beta/lib/vant.min.js' 617 css: ['https://cdn.jsdelivr.net/npm/vant@2.4.7/lib/index.css'],
594 ] 618 js: [
619 'https://cdn.jsdelivr.net/npm/vue@2.6.11/dist/vue.min.js',
620 'https://cdn.jsdelivr.net/npm/vue-router@3.1.5/dist/vue-router.min.js',
621 'https://cdn.jsdelivr.net/npm/axios@0.19.2/dist/axios.min.js',
622 'https://cdn.jsdelivr.net/npm/vuex@3.1.2/dist/vuex.min.js',
623 'https://cdn.jsdelivr.net/npm/vant@2.4.7/lib/index.min.js'
624 ]
625 }
595 } 626 }
596 module.exports = { 627 module.exports = {
597 configureWebpack: config => { 628 configureWebpack: config => {
598 config.name = name 629 config.name = name
599 // 为生产环境修改配置... 630 // 为生产环境修改配置...
600 if (IS_PROD) { 631 if (IS_PROD) {
601 // externals 632 // externals
602 config.externals = externals 633 config.externals = externals
603 }; 634 }
604 }, 635 },
605 chainWebpack: config => { 636 chainWebpack: config => {
606 // 添加CDN参数到htmlWebpackPlugin配置中, 详见public/index.html 修改 637 /**
638 * 添加CDN参数到htmlWebpackPlugin配置中
639 */
607 config.plugin('html').tap(args => { 640 config.plugin('html').tap(args => {
608 if (IS_PROD) { 641 if (IS_PROD) {
609 // html中添加cdn 642 args[0].cdn = cdn.build
610 args[0].cdn = cdn 643 } else {
611 } 644 args[0].cdn = cdn.dev
645 }
612 return args 646 return args
613 }) 647 })
614 } 648 }
615 }; 649 }
616 ``` 650 ```
617  在 public/index.html 中添加 651
652 在 public/index.html 中添加
618 653
619 ```javascript 654 ```javascript
620 <!-- 使用CDNCSS文件 --> 655 <!-- 使用CDNCSS文件 -->
621 <% for (var i in 656 <% for (var i in
622 htmlWebpackPlugin.options.cdn&&htmlWebpackPlugin.options.cdn.css) { %> 657 htmlWebpackPlugin.options.cdn&&htmlWebpackPlugin.options.cdn.css) { %>
658 <link href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" rel="preload" as="style" />
623 <link href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" rel="stylesheet" /> 659 <link href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" rel="stylesheet" />
624 <% } %> 660 <% } %>
625 <!-- 使用CDN加速的JS文件,配置在vue.config.js --> 661 <!-- 使用CDN加速的JS文件,配置在vue.config.js -->
...@@ -633,9 +669,12 @@ module.exports = { ...@@ -633,9 +669,12 @@ module.exports = {
633 669
634 ### <span id="console">✅ 去掉 console.log </span> 670 ### <span id="console">✅ 去掉 console.log </span>
635 671
672 保留了测试环境和本地环境的 `console.log`
673
636 ```bash 674 ```bash
637 npm i -D babel-plugin-transform-remove-console 675 npm i -D babel-plugin-transform-remove-console
638 ``` 676 ```
677
639 在 babel.config.js 中配置 678 在 babel.config.js 中配置
640 679
641 ```javascript 680 ```javascript
...@@ -661,19 +700,82 @@ module.exports = { ...@@ -661,19 +700,82 @@ module.exports = {
661 presets: [['@vue/cli-plugin-babel/preset', {useBuiltIns: 'entry'}]], 700 presets: [['@vue/cli-plugin-babel/preset', {useBuiltIns: 'entry'}]],
662 plugins 701 plugins
663 } 702 }
703 ```
704
705 [▲ 回顶部](#top)
706
707 ### <span id="chunks">✅ splitChunks 单独打包第三方模块</span>
664 708
709 ```javascript
710 module.exports = {
711 chainWebpack: config => {
712 config.when(IS_PROD, config => {
713 config
714 .plugin('ScriptExtHtmlWebpackPlugin')
715 .after('html')
716 .use('script-ext-html-webpack-plugin', [
717 {
718 // 将 runtime 作为内联引入不单独存在
719 inline: /runtime\..*\.js$/
720 }
721 ])
722 .end()
723 config.optimization.splitChunks({
724 chunks: 'all',
725 cacheGroups: {
726 // cacheGroups 下可以可以配置多个组,每个组根据test设置条件,符合test条件的模块
727 commons: {
728 name: 'chunk-commons',
729 test: resolve('src/components'),
730 minChunks: 3, // 被至少用三次以上打包分离
731 priority: 5, // 优先级
732 reuseExistingChunk: true // 表示是否使用已有的 chunk,如果为 true 则表示如果当前的 chunk 包含的模块已经被抽取出去了,那么将不会重新生成新的。
733 },
734 node_vendors: {
735 name: 'chunk-libs',
736 chunks: 'initial', // 只打包初始时依赖的第三方
737 test: /[\\/]node_modules[\\/]/,
738 priority: 10
739 },
740 vantUI: {
741 name: 'chunk-vantUI', // 单独将 vantUI 拆包
742 priority: 20, // 数字大权重到,满足多个 cacheGroups 的条件时候分到权重高的
743 test: /[\\/]node_modules[\\/]_?vant(.*)/
744 }
745 }
746 })
747 config.optimization.runtimeChunk('single')
748 })
749 }
750 }
665 ``` 751 ```
666 752
667 [▲ 回顶部](#top) 753 [▲ 回顶部](#top)
668 754
669 ### <span id="ie">✅ 添加 IE 兼容 </span> 755 ### <span id="ie">✅ 添加 IE 兼容 </span>
670 756
671 [▲ 回顶部](#top) 757 ```bash
758 npm i -S @babel/polyfill
759 ```
672 760
673 ### <span id="console">✅ 去掉 console.log </span> 761 `main.js` 中添加
674 [▲ 回顶部](#top) 762
763 ```javascript
764 import '@babel/polyfill'
765 ```
766
767 配置 `babel.config.js`
768
769 ```javascript
770 const plugins = []
675 771
772 module.exports = {
773 presets: [['@vue/cli-plugin-babel/preset', {useBuiltIns: 'entry'}]],
774 plugins
775 }
776 ```
676 777
778 [▲ 回顶部](#top)
677 779
678 #### 总结 780 #### 总结
679 781
......
...@@ -5,11 +5,11 @@ ...@@ -5,11 +5,11 @@
5 <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> 5 <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
6 <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"> 6 <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
7 <link rel="icon" href="<%= BASE_URL %>favicon.ico"> 7 <link rel="icon" href="<%= BASE_URL %>favicon.ico">
8 <% for (var i in 8 <!-- <% for (var i in
9 htmlWebpackPlugin.options.cdn&&htmlWebpackPlugin.options.cdn.css) { %> 9 htmlWebpackPlugin.options.cdn&&htmlWebpackPlugin.options.cdn.css) { %>
10 <link href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" rel="preload" as="style" /> 10 <link href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" rel="preload" as="style" />
11 <link href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" rel="stylesheet" /> 11 <link href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" rel="stylesheet" />
12 <% } %> 12 <% } %> -->
13 <title><%= webpackConfig.name %></title> 13 <title><%= webpackConfig.name %></title>
14 </head> 14 </head>
15 <body> 15 <body>
...@@ -18,10 +18,10 @@ ...@@ -18,10 +18,10 @@
18 </noscript> 18 </noscript>
19 <div id="app"></div> 19 <div id="app"></div>
20 <!-- 使用CDN加速的JS文件,配置在vue.config.js下 --> 20 <!-- 使用CDN加速的JS文件,配置在vue.config.js下 -->
21 <% for (var i in 21 <!-- <% for (var i in
22 htmlWebpackPlugin.options.cdn&&htmlWebpackPlugin.options.cdn.js) { %> 22 htmlWebpackPlugin.options.cdn&&htmlWebpackPlugin.options.cdn.js) { %>
23 <script src="<%= htmlWebpackPlugin.options.cdn.js[i] %>"></script> 23 <script src="<%= htmlWebpackPlugin.options.cdn.js[i] %>"></script>
24 <% } %> 24 <% } %> -->
25 <!-- built files will be auto injected --> 25 <!-- built files will be auto injected -->
26 </body> 26 </body>
27 </html> 27 </html>
......
...@@ -4,10 +4,19 @@ ...@@ -4,10 +4,19 @@
4 <router-view v-if="$route.meta.keepAlive"></router-view> 4 <router-view v-if="$route.meta.keepAlive"></router-view>
5 </keep-alive> 5 </keep-alive>
6 <router-view v-if="!$route.meta.keepAlive"></router-view> 6 <router-view v-if="!$route.meta.keepAlive"></router-view>
7 <!-- tabbar -->
8 <TabBar></TabBar>
7 </div> 9 </div>
8 </template> 10 </template>
9 <script> 11 <script>
12 import TabBar from '@/components/TabBar'
13
10 export default { 14 export default {
11 name: 'App' 15 name: 'App',
16 components: {
17 TabBar
18 },
12 } 19 }
13 </script> 20 </script>
21 <style lang="scss">
22 </style>
...\ No newline at end of file ...\ No newline at end of file
......
1 @import './variables.scss'; 1 @import './variables.scss';
2 @import './mixin.scss'; 2 @import './mixin.scss';
3 /* http://meyerweb.com/eric/tools/css/reset/
4 v2.0 | 20110126
5 License: none (public domain)
6 */
7
8 html, body, div, span, applet, object, iframe,
9 h1, h2, h3, h4, h5, h6, p, blockquote, pre,
10 a, abbr, acronym, address, big, cite, code,
11 del, dfn, em, img, ins, kbd, q, s, samp,
12 small, strike, strong, sub, sup, tt, var,
13 b, u, i, center,
14 dl, dt, dd, ol, ul, li,
15 fieldset, form, label, legend,
16 table, caption, tbody, tfoot, thead, tr, th, td,
17 article, aside, canvas, details, embed,
18 figure, figcaption, footer, header, hgroup,
19 menu, nav, output, ruby, section, summary,
20 time, mark, audio, video {
21 margin: 0;
22 padding: 0;
23 border: 0;
24 font-size: 100%;
25 font: inherit;
26 vertical-align: baseline;
27 }
28 /* HTML5 display-role reset for older browsers */
29 article, aside, details, figcaption, figure,
30 footer, header, hgroup, menu, nav, section {
31 display: block;
32 }
33 body {
34 line-height: 1;
35 }
36 ol, ul {
37 list-style: none;
38 }
39 blockquote, q {
40 quotes: none;
41 }
42 blockquote:before, blockquote:after,
43 q:before, q:after {
44 content: '';
45 content: none;
46 }
47 table {
48 border-collapse: collapse;
49 border-spacing: 0;
50 }
51
52 .app-container{ 3 .app-container{
53 padding-bottom:50px 4 padding-bottom:50px
54 } 5 }
...\ No newline at end of file ...\ No newline at end of file
......
1 <template> 1 <template>
2 <div> 2 <div>
3 <van-tabbar fixed v-model="active" @change="onChange"> 3 <van-tabbar fixed route>
4 <van-tabbar-item icon="home-o">首页</van-tabbar-item> 4 <van-tabbar-item to="/" icon="home-o">
5 <van-tabbar-item icon="good-job-o">github</van-tabbar-item> 5 首页
6 </van-tabbar> 6 </van-tabbar-item>
7 <van-tabbar-item to="/about" icon="user-o">
8 关于我
9 </van-tabbar-item>
10 </van-tabbar>
11 <!-- <van-tabbar fixed v-model="active" @change="onChange">
12 <van-tabbar-item to="/home" icon="home-o">首页</van-tabbar-item>
13 <van-tabbar-item to="/about" icon="user-o">关于我</van-tabbar-item>
14 </van-tabbar> -->
7 </div> 15 </div>
8 </template> 16 </template>
9 17
10 <script> 18 <script>
11 import _ from 'lodash' 19
12 console.log(_.join(['a', 'b'], '~'))
13 export default { 20 export default {
14 name: 'TabBar', 21 name: 'TabBar',
15 data() { 22 data() {
...@@ -18,9 +25,9 @@ export default { ...@@ -18,9 +25,9 @@ export default {
18 } 25 }
19 }, 26 },
20 methods: { 27 methods: {
21 onChange(index) { 28 // onChange(index) {
22 if (index === 1) window.location.href = 'https://github.com/sunniejs/vue-h5-template' 29 // if (index === 1) window.location.href = 'https://github.com/sunniejs/vue-h5-template'
23 } 30 // }
24 } 31 }
25 } 32 }
26 </script> 33 </script>
......
...@@ -4,5 +4,6 @@ module.exports = { ...@@ -4,5 +4,6 @@ module.exports = {
4 baseUrl: 'http://localhost:9018', // 项目地址 4 baseUrl: 'http://localhost:9018', // 项目地址
5 baseApi: 'https://test.xxx.com/api', // 本地api请求地址 5 baseApi: 'https://test.xxx.com/api', // 本地api请求地址
6 APPID: 'xxx', 6 APPID: 'xxx',
7 APPSECRET: 'xxx' 7 APPSECRET: 'xxx',
8 $cdn:'https://imgs.solui.cn'
8 } 9 }
......
...@@ -4,5 +4,6 @@ module.exports = { ...@@ -4,5 +4,6 @@ module.exports = {
4 baseUrl: 'https://www.xxx.com/', // 正式项目地址 4 baseUrl: 'https://www.xxx.com/', // 正式项目地址
5 baseApi: 'https://www.xxx.com/api', // 正式api请求地址 5 baseApi: 'https://www.xxx.com/api', // 正式api请求地址
6 APPID: 'xxx', 6 APPID: 'xxx',
7 APPSECRET: 'xxx' 7 APPSECRET: 'xxx',
8 $cdn:'https://imgs.solui.cn'
8 } 9 }
......
...@@ -3,5 +3,6 @@ module.exports = { ...@@ -3,5 +3,6 @@ module.exports = {
3 baseUrl: 'https://test.xxx.com', // 测试项目地址 3 baseUrl: 'https://test.xxx.com', // 测试项目地址
4 baseApi: 'https://test.xxx.com/api', // 测试api请求地址 4 baseApi: 'https://test.xxx.com/api', // 测试api请求地址
5 APPID: 'xxx', 5 APPID: 'xxx',
6 APPSECRET: 'xxx' 6 APPSECRET: 'xxx',
7 $cdn:'https://imgs.solui.cn'
7 } 8 }
......
...@@ -5,7 +5,7 @@ import App from './App.vue' ...@@ -5,7 +5,7 @@ import App from './App.vue'
5 import router from './router' 5 import router from './router'
6 import store from './store' 6 import store from './store'
7 // 引入全局样式 7 // 引入全局样式
8 import '@/assets/css/index.scss' 8 // import '@/assets/css/index.scss'
9 9
10 // 全局引入按需引入UI库 vant 10 // 全局引入按需引入UI库 vant
11 import '@/plugins/vant' 11 import '@/plugins/vant'
......
...@@ -6,45 +6,31 @@ ...@@ -6,45 +6,31 @@
6 <h2 class="demo-home__desc"> 6 <h2 class="demo-home__desc">
7 A vue h5 template with Vant UI 7 A vue h5 template with Vant UI
8 </h2> 8 </h2>
9 <div class="list">
10 <div class="item">项目地址: <a href="https://github.com/sunniejs">https://github.com/sunniejs</a></div>
11 <div class="item">项目作者: sunnie</div>
12 <div class="item"></div>
13 <div class="author"></div>
14 </div>
9 </div> 15 </div>
10 <van-cell icon="success" v-for="item in list" :key="item" :title="item" />
11 <!-- tabbar -->
12 <TabBar></TabBar>
13 </div> 16 </div>
14 </template> 17 </template>
15 18
16 <script> 19 <script>
17 import TabBar from '@/components/TabBar'
18 // 请求接口 20 // 请求接口
19 import {getUserInfo} from '@/api/user.js' 21 import { getUserInfo } from '@/api/user.js'
20 22
21 export default { 23 export default {
22 components: {
23 TabBar
24 },
25
26 data() { 24 data() {
27 return { 25 return {
28 list: [ 26
29 'Vue-cli4',
30 'VantUI组件按需加载',
31 'Sass',
32 'Webpack 4',
33 'Vue-router',
34 'Vuex',
35 'Axios封装',
36 'rem适配方案',
37 '多环境配置',
38 '生产环境cdn优化首屏加速',
39 'babel低版本浏览器兼容',
40 'Eslint+Pettier统一开发规范'
41 ]
42 } 27 }
43 }, 28 },
44 29
45 computed: {}, 30 computed: {},
46 31
47 mounted() { 32 mounted() {
33
48 this.initData() 34 this.initData()
49 }, 35 },
50 36
...@@ -52,10 +38,10 @@ export default { ...@@ -52,10 +38,10 @@ export default {
52 // 请求数据案例 38 // 请求数据案例
53 initData() { 39 initData() {
54 // 请求接口数据,仅作为展示,需要配置src->config下环境文件 40 // 请求接口数据,仅作为展示,需要配置src->config下环境文件
55 const params = {user: 'sunnie'} 41 const params = { user: 'sunnie' }
56 getUserInfo(params) 42 getUserInfo(params)
57 .then(() => {}) 43 .then(() => { })
58 .catch(() => {}) 44 .catch(() => { })
59 } 45 }
60 } 46 }
61 } 47 }
...@@ -64,6 +50,7 @@ export default { ...@@ -64,6 +50,7 @@ export default {
64 .app-container { 50 .app-container {
65 .warpper { 51 .warpper {
66 padding: 12px; 52 padding: 12px;
53 background: $background-color;
67 .demo-home__title { 54 .demo-home__title {
68 margin: 0 0 6px; 55 margin: 0 0 6px;
69 font-size: 32px; 56 font-size: 32px;
...@@ -85,6 +72,23 @@ export default { ...@@ -85,6 +72,23 @@ export default {
85 color: rgba(69, 90, 100, 0.6); 72 color: rgba(69, 90, 100, 0.6);
86 font-size: 14px; 73 font-size: 14px;
87 } 74 }
75 .list {
76 display: flex;
77 flex-direction: column;
78 color: #666;
79 font-size: 14px;
80 .item {
81 font-size: 14px;
82 line-height: 24px;
83 }
84 }
85
86 .author {
87 margin:10px auto;
88 width: 200px;
89 height: 200px;
90 background: url($cdn+'/weapp/me.png') center / contain no-repeat;
91 }
88 } 92 }
89 } 93 }
90 </style> 94 </style>
......
...@@ -8,36 +8,35 @@ ...@@ -8,36 +8,35 @@
8 </h2> 8 </h2>
9 </div> 9 </div>
10 <van-cell icon="success" v-for="item in list" :key="item" :title="item" /> 10 <van-cell icon="success" v-for="item in list" :key="item" :title="item" />
11 <!-- tabbar -->
12 <TabBar></TabBar>
13 </div> 11 </div>
14 </template> 12 </template>
15 13
16 <script> 14 <script>
17 import TabBar from '@/components/TabBar' 15 import TabBar from '@/components/TabBar'
18 // 请求接口 16 // 请求接口
19 import {getUserInfo} from '@/api/user.js' 17 import { getUserInfo } from '@/api/user.js'
20 18
21 export default { 19 export default {
22 components: {
23 TabBar
24 },
25 20
26 data() { 21 data() {
27 return { 22 return {
28 list: [ 23 list: [
29 'Vue-cli4', 24 'Vue-cli4',
30 'VantUI组件按需加载', 25 ' 配置多环境变量',
31 'Sass', 26 ' VantUI 组件按需加载',
27 ' Sass',
32 'Webpack 4', 28 'Webpack 4',
33 'Vue-router',
34 'Vuex', 29 'Vuex',
35 'Axios封装', 30 ' Axios 封装及接口管理',
36 'rem适配方案', 31 'Vue-router',
37 '多环境配置', 32 'vue.config.js 基础配置',
38 '生产环境cdn优化首屏加速', 33 '配置 proxy 跨域',
39 'babel低版本浏览器兼容', 34 '配置 alias 别名',
40 'Eslint+Pettier统一开发规范' 35 '配置 打包分析',
36 '配置 externals 引入 cdn 资源',
37 '去掉 console.log',
38 'splitChunks 单独打包第三方模块',
39 ' 添加 IE 兼容'
41 ] 40 ]
42 } 41 }
43 }, 42 },
...@@ -52,19 +51,19 @@ export default { ...@@ -52,19 +51,19 @@ export default {
52 // 请求数据案例 51 // 请求数据案例
53 initData() { 52 initData() {
54 // 请求接口数据,仅作为展示,需要配置src->config下环境文件 53 // 请求接口数据,仅作为展示,需要配置src->config下环境文件
55 const params = {user: 'sunnie'} 54 const params = { user: 'sunnie' }
56 getUserInfo(params) 55 getUserInfo(params)
57 .then(() => {}) 56 .then(() => { })
58 .catch(() => {}) 57 .catch(() => { })
59 } 58 }
60 } 59 }
61 } 60 }
62 </script> 61 </script>
63 <style lang="scss" scoped> 62 <style lang="scss" scoped>
64 // @import '@/assets/css/index.scss';
65 .app-container { 63 .app-container {
66 .warpper { 64 .warpper {
67 padding: 12px; 65 padding: 12px;
66 background: $background-color;
68 .demo-home__title { 67 .demo-home__title {
69 margin: 0 0 6px; 68 margin: 0 0 6px;
70 font-size: 32px; 69 font-size: 32px;
......
...@@ -9,44 +9,31 @@ const name = defaultSettings.title || 'vue mobile template' ...@@ -9,44 +9,31 @@ const name = defaultSettings.title || 'vue mobile template'
9 const IS_PROD = ['production', 'prod'].includes(process.env.NODE_ENV) 9 const IS_PROD = ['production', 'prod'].includes(process.env.NODE_ENV)
10 10
11 // externals 11 // externals
12 const externals = { 12 // const externals = {
13 vue: 'Vue', 13 // vue: 'Vue',
14 'vue-router': 'VueRouter', 14 // 'vue-router': 'VueRouter',
15 vuex: 'Vuex', 15 // vuex: 'Vuex',
16 vant: 'vant', 16 // vant: 'vant',
17 axios: 'axios' 17 // axios: 'axios'
18 } 18 // }
19 // CDN外链,会插入到index.html中 19 // CDN外链,会插入到index.html中
20 const cdn = {
21 // 开发环境
22 dev: {
23 css: [
24 ],
25 js: []
26 },
27 // 生产环境
28 build: {
29 css: ['https://cdn.jsdelivr.net/npm/vant@2.4.7/lib/index.css'],
30 js: [
31 'https://cdn.jsdelivr.net/npm/vue@2.6.11/dist/vue.min.js',
32 'https://cdn.jsdelivr.net/npm/vue-router@3.1.5/dist/vue-router.min.js',
33 'https://cdn.jsdelivr.net/npm/axios@0.19.2/dist/axios.min.js',
34 'https://cdn.jsdelivr.net/npm/vuex@3.1.2/dist/vuex.min.js',
35 'https://cdn.jsdelivr.net/npm/vant@2.4.7/lib/index.min.js'
36 ]
37 }
38 }
39 // const cdn = { 20 // const cdn = {
40 // css: ['https://cdn.jsdelivr.net/npm/vant@2.4.7/lib/index.css'], 21 // // 开发环境
41 // js: [ 22 // dev: {
42 // 'https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.min.js', 23 // css: [],
43 // 'https://cdnjs.cloudflare.com/ajax/libs/vue-router/3.1.5/vue-router.min.js', 24 // js: []
44 // 'https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.2/axios.min.js', 25 // },
45 // 'https://cdnjs.cloudflare.com/ajax/libs/vuex/3.1.2/vuex.min.js', 26 // // 生产环境
46 // 'https://cdn.jsdelivr.net/npm/vant@2.4.7/lib/index.min.js', 27 // build: {
47 // 'https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/crypto-js.min.js', 28 // css: ['https://cdn.jsdelivr.net/npm/vant@2.4.7/lib/index.css'],
48 29 // js: [
49 // ] 30 // 'https://cdn.jsdelivr.net/npm/vue@2.6.11/dist/vue.min.js',
31 // 'https://cdn.jsdelivr.net/npm/vue-router@3.1.5/dist/vue-router.min.js',
32 // 'https://cdn.jsdelivr.net/npm/axios@0.19.2/dist/axios.min.js',
33 // 'https://cdn.jsdelivr.net/npm/vuex@3.1.2/dist/vuex.min.js',
34 // 'https://cdn.jsdelivr.net/npm/vant@2.4.7/lib/index.min.js'
35 // ]
36 // }
50 // } 37 // }
51 38
52 module.exports = { 39 module.exports = {
...@@ -55,7 +42,7 @@ module.exports = { ...@@ -55,7 +42,7 @@ module.exports = {
55 outputDir: 'dist', // 生产环境构建文件的目录 42 outputDir: 'dist', // 生产环境构建文件的目录
56 assetsDir: 'static', // outputDir的静态资源(js、css、img、fonts)目录 43 assetsDir: 'static', // outputDir的静态资源(js、css、img、fonts)目录
57 lintOnSave: false, 44 lintOnSave: false,
58 productionSourceMap: !IS_PROD, // 生产环境的 source map 45 productionSourceMap: false, // 如果你不需要生产环境的 source map,可以将其设置为 false 以加速生产环境构建。
59 devServer: { 46 devServer: {
60 port: 9020, // 端口 47 port: 9020, // 端口
61 open: false, // 启动后打开浏览器 48 open: false, // 启动后打开浏览器
...@@ -76,16 +63,27 @@ module.exports = { ...@@ -76,16 +63,27 @@ module.exports = {
76 // } 63 // }
77 // } 64 // }
78 }, 65 },
79 66 css: {
67 extract: IS_PROD,
68 sourceMap: false,
69 loaderOptions: {
70 scss: {
71 // 向全局sass样式传入共享的全局变量, $src可以配置图片cdn前缀
72 // 详情: https://cli.vuejs.org/guide/css.html#passing-options-to-pre-processor-loaders
73 prependData: `
74 @import "assets/css/index.scss";
75 $cdn: "${defaultSettings.$cdn}";
76 `
77 }
78 }
79 },
80 configureWebpack: config => { 80 configureWebpack: config => {
81 config.name = name 81 config.name = name
82
82 // 为生产环境修改配置... 83 // 为生产环境修改配置...
83 if (IS_PROD) { 84 // if (IS_PROD) {
84 // externals 85 // // externals
85 config.externals = externals 86 // config.externals = externals
86 }
87 // 为开发环境修改配置...
88 // if (process.env.NODE_ENV === 'development') {
89 // } 87 // }
90 }, 88 },
91 89
...@@ -100,7 +98,34 @@ module.exports = { ...@@ -100,7 +98,34 @@ module.exports = {
100 .set('api', resolve('src/api')) 98 .set('api', resolve('src/api'))
101 .set('views', resolve('src/views')) 99 .set('views', resolve('src/views'))
102 .set('components', resolve('src/components')) 100 .set('components', resolve('src/components'))
103 // 打包分析 101
102 /**
103 * 添加CDN参数到htmlWebpackPlugin配置中
104 */
105 // config.plugin('html').tap(args => {
106 // if (IS_PROD) {
107 // args[0].cdn = cdn.build
108 // } else {
109 // args[0].cdn = cdn.dev
110 // }
111 // return args
112 // })
113
114 /**
115 * 设置保留空格
116 */
117 config.module
118 .rule('vue')
119 .use('vue-loader')
120 .loader('vue-loader')
121 .tap(options => {
122 options.compilerOptions.preserveWhitespace = true
123 return options
124 })
125 .end()
126 /**
127 * 打包分析
128 */
104 if (IS_PROD) { 129 if (IS_PROD) {
105 config.plugin('webpack-report').use(BundleAnalyzerPlugin, [ 130 config.plugin('webpack-report').use(BundleAnalyzerPlugin, [
106 { 131 {
...@@ -108,69 +133,46 @@ module.exports = { ...@@ -108,69 +133,46 @@ module.exports = {
108 } 133 }
109 ]) 134 ])
110 } 135 }
111 /** 136 config
112 * 添加CDN参数到htmlWebpackPlugin配置中 137 // https://webpack.js.org/configuration/devtool/#development
113 */ 138 .when(!IS_PROD, config => config.devtool('cheap-source-map'))
114 config.plugin('html').tap(args => {
115 if (IS_PROD) {
116 args[0].cdn = cdn.build
117 } else {
118 args[0].cdn = cdn.dev
119 }
120
121 return args
122 })
123 // set preserveWhitespace
124 // config.module
125 // .rule('vue')
126 // .use('vue-loader')
127 // .loader('vue-loader')
128 // .tap(options => {
129 // options.compilerOptions.preserveWhitespace = true
130 // return options
131 // })
132 // .end()
133 139
134 // config 140 config.when(IS_PROD, config => {
135 // // https://webpack.js.org/configuration/devtool/#development 141 config
136 // .when(process.env.NODE_ENV === 'development', config => config.devtool('cheap-source-map')) 142 .plugin('ScriptExtHtmlWebpackPlugin')
137 143 .after('html')
138 // config.when(IS_PROD, config => { 144 .use('script-ext-html-webpack-plugin', [
139 // config 145 {
140 // .plugin('ScriptExtHtmlWebpackPlugin') 146 // 将 runtime 作为内联引入不单独存在
141 // .after('html') 147 inline: /runtime\..*\.js$/
142 // .use('script-ext-html-webpack-plugin', [ 148 }
143 // { 149 ])
144 // // `runtime` must same as runtimeChunk name. default is `runtime` 150 .end()
145 // inline: /runtime\..*\.js$/ 151 config.optimization.splitChunks({
146 // } 152 chunks: 'all',
147 // ]) 153 cacheGroups: {
148 // .end() 154 // cacheGroups 下可以可以配置多个组,每个组根据test设置条件,符合test条件的模块
149 // config.optimization.splitChunks({ 155 commons: {
150 // chunks: 'all', 156 name: 'chunk-commons',
151 // cacheGroups: { 157 test: resolve('src/components'),
152 // // cacheGroups 下可以可以配置多个组,每个组根据test设置条件,符合test条件的模块 158 minChunks: 3, // 被至少用三次以上打包分离
153 // commons: { 159 priority: 5, // 优先级
154 // name: 'chunk-commons', 160 reuseExistingChunk: true // 表示是否使用已有的 chunk,如果为 true 则表示如果当前的 chunk 包含的模块已经被抽取出去了,那么将不会重新生成新的。
155 // test: resolve('src/components'), 161 },
156 // minChunks: 3, // 被至少用三次以上打包分离 162 node_vendors: {
157 // priority: 5, // 优先级 163 name: 'chunk-libs',
158 // reuseExistingChunk: true // 复用其他chunk内已拥有的模块 164 chunks: 'initial', // 只打包初始时依赖的第三方
159 // }, 165 test: /[\\/]node_modules[\\/]/,
160 // // vantUI: { 166 priority: 10
161 // // name: 'chunk-vantUI', // 将 vant 打包到单独文件 167 },
162 // // priority: 20, 168 vantUI: {
163 // // test: /[\\/]node_modules[\\/]_?vant(.*)/ // in order to adapt to cnpm 169 name: 'chunk-vantUI', // 单独将 vantUI 拆包
164 // // }, 170 priority: 20, // 数字大权重到,满足多个 cacheGroups 的条件时候分到权重高的
165 // libs: { 171 test: /[\\/]node_modules[\\/]_?vant(.*)/
166 // name: 'chunk-libs', 172 }
167 // chunks: 'initial', // only package third parties that are initially dependent 173 }
168 // test: /[\\/]node_modules[\\/]/, 174 })
169 // priority: 10 175 config.optimization.runtimeChunk('single')
170 // } 176 })
171 // }
172 // })
173 // config.optimization.runtimeChunk('single')
174 // })
175 } 177 }
176 } 178 }
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!