dev
Showing
10 changed files
with
430 additions
and
187 deletions
| ... | @@ -25,8 +25,14 @@ | ... | @@ -25,8 +25,14 @@ |
| 25 | - [√ Axios 封装及接口管理](#axios) | 25 | - [√ Axios 封装及接口管理](#axios) |
| 26 | - [√ Vue-router](#router) | 26 | - [√ Vue-router](#router) |
| 27 | - [√ vue.config.js 基础配置](#base) | 27 | - [√ vue.config.js 基础配置](#base) |
| 28 | - [√ vue.config.js 配置 proxy 跨域](#proxy) | 28 | - [√ 配置 proxy 跨域](#proxy) |
| 29 | - [√ vue.config.js 配置 proxy 跨域](#proxy) | 29 | - [√ 配置 alias 别名](#alias) |
| 30 | - [√ 配置 打包分析](#bundle) | ||
| 31 | - [√ 配置 externals 引入 cdn 资源 ](#externals) | ||
| 32 | - [√ 去掉 console.log ](#console) | ||
| 33 | - [√ splitChunks ](#console) | ||
| 34 | - [√ 添加 IE 兼容 ](#ie) | ||
| 35 | |||
| 30 | 36 | ||
| 31 | * Vuex | 37 | * Vuex |
| 32 | * Axios 封装 | 38 | * Axios 封装 |
| ... | @@ -476,7 +482,7 @@ module.exports = { | ... | @@ -476,7 +482,7 @@ module.exports = { |
| 476 | 482 | ||
| 477 | [▲ 回顶部](#top) | 483 | [▲ 回顶部](#top) |
| 478 | 484 | ||
| 479 | ### <span id="proxy">✅ vue.config.js 配置 proxy 跨域 </span> | 485 | ### <span id="proxy">✅ 配置 proxy 跨域 </span> |
| 480 | 486 | ||
| 481 | 如果你的项目需要跨域设置,你需要打来 `vue.config.js` `proxy` 注释 并且配置相应参数 | 487 | 如果你的项目需要跨域设置,你需要打来 `vue.config.js` `proxy` 注释 并且配置相应参数 |
| 482 | 488 | ||
| ... | @@ -515,10 +521,160 @@ export function getUserInfo(params) { | ... | @@ -515,10 +521,160 @@ export function getUserInfo(params) { |
| 515 | 521 | ||
| 516 | [▲ 回顶部](#top) | 522 | [▲ 回顶部](#top) |
| 517 | 523 | ||
| 518 | ### <span id="proxy">✅ vue.config.js 配置 proxy 跨域 </span> | 524 | ### <span id="alias">✅ 配置 alias 别名 </span> |
| 525 | |||
| 526 | ```javascript | ||
| 527 | const path = require("path"); | ||
| 528 | const resolve = dir => path.join(__dirname, dir); | ||
| 529 | const IS_PROD = ["production", "prod"].includes(process.env.NODE_ENV); | ||
| 530 | |||
| 531 | module.exports = { | ||
| 532 | chainWebpack: config => { | ||
| 533 | // 添加别名 | ||
| 534 | config.resolve.alias | ||
| 535 | .set('@', resolve('src')) | ||
| 536 | .set('assets', resolve('src/assets')) | ||
| 537 | .set('api', resolve('src/api')) | ||
| 538 | .set('views', resolve('src/views')) | ||
| 539 | .set('components', resolve('src/components')) | ||
| 540 | } | ||
| 541 | }; | ||
| 542 | ``` | ||
| 543 | [▲ 回顶部](#top) | ||
| 544 | |||
| 545 | ### <span id="bundle">✅ 配置 打包分析 </span> | ||
| 546 | |||
| 547 | ```javascript | ||
| 548 | const BundleAnalyzerPlugin = require("webpack-bundle-analyzer") | ||
| 549 | .BundleAnalyzerPlugin; | ||
| 550 | |||
| 551 | module.exports = { | ||
| 552 | chainWebpack: config => { | ||
| 553 | // 打包分析 | ||
| 554 | if (IS_PROD) { | ||
| 555 | config.plugin("webpack-report").use(BundleAnalyzerPlugin, [ | ||
| 556 | { | ||
| 557 | analyzerMode: "static" | ||
| 558 | } | ||
| 559 | ]); | ||
| 560 | } | ||
| 561 | } | ||
| 562 | }; | ||
| 563 | ``` | ||
| 564 | ```bash | ||
| 565 | npm run build | ||
| 566 | ``` | ||
| 567 | [▲ 回顶部](#top) | ||
| 568 | |||
| 569 | ### <span id="proxy">✅ 配置 externals 引入 cdn 资源 </span> | ||
| 570 | |||
| 571 | ```javascript | ||
| 572 | const defaultSettings = require('./src/config/index.js') | ||
| 573 | const name = defaultSettings.title || 'vue mobile template' | ||
| 574 | const IS_PROD = ["production", "prod"].includes(process.env.NODE_ENV); | ||
| 575 | |||
| 576 | // externals | ||
| 577 | const externals = { | ||
| 578 | vue: 'Vue', | ||
| 579 | 'vue-router': 'VueRouter', | ||
| 580 | vuex: 'Vuex', | ||
| 581 | vant: 'vant', | ||
| 582 | axios: 'axios' | ||
| 583 | } | ||
| 584 | // cdn | ||
| 585 | const cdn = { | ||
| 586 | css: ['https://cdn.jsdelivr.net/npm/vant@beta/lib/index.css'], | ||
| 587 | js: [ | ||
| 588 | 'https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js', | ||
| 589 | 'https://cdnjs.cloudflare.com/ajax/libs/vue-router/3.0.6/vue-router.min.js', | ||
| 590 | 'https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.min.js', | ||
| 591 | 'https://cdnjs.cloudflare.com/ajax/libs/vuex/3.1.1/vuex.min.js', | ||
| 592 | 'https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/crypto-js.min.js', | ||
| 593 | 'https://cdn.jsdelivr.net/npm/vant@beta/lib/vant.min.js' | ||
| 594 | ] | ||
| 595 | } | ||
| 596 | module.exports = { | ||
| 597 | configureWebpack: config => { | ||
| 598 | config.name = name | ||
| 599 | // 为生产环境修改配置... | ||
| 600 | if (IS_PROD) { | ||
| 601 | // externals | ||
| 602 | config.externals = externals | ||
| 603 | }; | ||
| 604 | }, | ||
| 605 | chainWebpack: config => { | ||
| 606 | // 添加CDN参数到htmlWebpackPlugin配置中, 详见public/index.html 修改 | ||
| 607 | config.plugin('html').tap(args => { | ||
| 608 | if (IS_PROD) { | ||
| 609 | // html中添加cdn | ||
| 610 | args[0].cdn = cdn | ||
| 611 | } | ||
| 612 | return args | ||
| 613 | }) | ||
| 614 | } | ||
| 615 | }; | ||
| 616 | ``` | ||
| 617 | 在 public/index.html 中添加 | ||
| 618 | |||
| 619 | ```javascript | ||
| 620 | <!-- 使用CDN的CSS文件 --> | ||
| 621 | <% for (var i in | ||
| 622 | htmlWebpackPlugin.options.cdn&&htmlWebpackPlugin.options.cdn.css) { %> | ||
| 623 | <link href="<%= htmlWebpackPlugin.options.cdn.css[i] %>" rel="stylesheet" /> | ||
| 624 | <% } %> | ||
| 625 | <!-- 使用CDN加速的JS文件,配置在vue.config.js下 --> | ||
| 626 | <% for (var i in | ||
| 627 | htmlWebpackPlugin.options.cdn&&htmlWebpackPlugin.options.cdn.js) { %> | ||
| 628 | <script src="<%= htmlWebpackPlugin.options.cdn.js[i] %>"></script> | ||
| 629 | <% } %> | ||
| 630 | ``` | ||
| 631 | |||
| 632 | [▲ 回顶部](#top) | ||
| 633 | |||
| 634 | ### <span id="console">✅ 去掉 console.log </span> | ||
| 635 | |||
| 636 | ```bash | ||
| 637 | npm i -D babel-plugin-transform-remove-console | ||
| 638 | ``` | ||
| 639 | 在 babel.config.js 中配置 | ||
| 640 | |||
| 641 | ```javascript | ||
| 642 | // 获取 VUE_APP_ENV 非 NODE_ENV,测试环境依然 console | ||
| 643 | const IS_PROD = ['production', 'prod'].includes(process.env.VUE_APP_ENV) | ||
| 644 | const plugins = [ | ||
| 645 | [ | ||
| 646 | 'import', | ||
| 647 | { | ||
| 648 | libraryName: 'vant', | ||
| 649 | libraryDirectory: 'es', | ||
| 650 | style: true | ||
| 651 | }, | ||
| 652 | 'vant' | ||
| 653 | ] | ||
| 654 | ] | ||
| 655 | // 去除 console.log | ||
| 656 | if (IS_PROD) { | ||
| 657 | plugins.push('transform-remove-console') | ||
| 658 | } | ||
| 659 | |||
| 660 | module.exports = { | ||
| 661 | presets: [['@vue/cli-plugin-babel/preset', {useBuiltIns: 'entry'}]], | ||
| 662 | plugins | ||
| 663 | } | ||
| 664 | |||
| 665 | ``` | ||
| 666 | |||
| 667 | [▲ 回顶部](#top) | ||
| 668 | |||
| 669 | ### <span id="ie">✅ 添加 IE 兼容 </span> | ||
| 519 | 670 | ||
| 520 | [▲ 回顶部](#top) | 671 | [▲ 回顶部](#top) |
| 521 | 672 | ||
| 673 | ### <span id="console">✅ 去掉 console.log </span> | ||
| 674 | [▲ 回顶部](#top) | ||
| 675 | |||
| 676 | |||
| 677 | |||
| 522 | #### 总结 | 678 | #### 总结 |
| 523 | 679 | ||
| 524 | 因为项目刚刚构建起来,后面还会持续更新,实际使用过程中一定还有很多问题,如果文章中有错误希望能够被指正,一起成长 | 680 | 因为项目刚刚构建起来,后面还会持续更新,实际使用过程中一定还有很多问题,如果文章中有错误希望能够被指正,一起成长 | ... | ... |
| 1 | module.exports = { | 1 | // 获取 VUE_APP_ENV 非 NODE_ENV,测试环境依然 console |
| 2 | presets: [['@vue/cli-plugin-babel/preset', {useBuiltIns: 'entry'}]], | 2 | const IS_PROD = ['production', 'prod'].includes(process.env.VUE_APP_ENV) |
| 3 | plugins: [ | 3 | const plugins = [ |
| 4 | [ | 4 | [ |
| 5 | 'import', | 5 | 'import', |
| 6 | { | 6 | { |
| ... | @@ -10,5 +10,13 @@ module.exports = { | ... | @@ -10,5 +10,13 @@ module.exports = { |
| 10 | }, | 10 | }, |
| 11 | 'vant' | 11 | 'vant' |
| 12 | ] | 12 | ] |
| 13 | ] | 13 | ] |
| 14 | // 去除 console.log | ||
| 15 | if (IS_PROD) { | ||
| 16 | plugins.push('transform-remove-console') | ||
| 17 | } | ||
| 18 | |||
| 19 | module.exports = { | ||
| 20 | presets: [['@vue/cli-plugin-babel/preset', {useBuiltIns: 'entry'}]], | ||
| 21 | plugins | ||
| 14 | } | 22 | } | ... | ... |
This diff could not be displayed because it is too large.
| ... | @@ -14,6 +14,7 @@ | ... | @@ -14,6 +14,7 @@ |
| 14 | "axios": "^0.19.2", | 14 | "axios": "^0.19.2", |
| 15 | "core-js": "^3.6.4", | 15 | "core-js": "^3.6.4", |
| 16 | "lib-flexible": "^0.3.2", | 16 | "lib-flexible": "^0.3.2", |
| 17 | "lodash": "^4.17.15", | ||
| 17 | "vant": "^2.4.7", | 18 | "vant": "^2.4.7", |
| 18 | "vue": "^2.6.11", | 19 | "vue": "^2.6.11", |
| 19 | "vue-router": "^3.1.5", | 20 | "vue-router": "^3.1.5", |
| ... | @@ -36,6 +37,7 @@ | ... | @@ -36,6 +37,7 @@ |
| 36 | "prettier": "^1.19.1", | 37 | "prettier": "^1.19.1", |
| 37 | "sass-loader": "^8.0.2", | 38 | "sass-loader": "^8.0.2", |
| 38 | "script-ext-html-webpack-plugin": "^2.1.4", | 39 | "script-ext-html-webpack-plugin": "^2.1.4", |
| 39 | "vue-template-compiler": "^2.6.11" | 40 | "vue-template-compiler": "^2.6.11", |
| 41 | "webpack-bundle-analyzer": "^3.7.0" | ||
| 40 | } | 42 | } |
| 41 | } | 43 | } | ... | ... |
src/components/HelloWorld.vue
deleted
100644 → 0
| 1 | <template> | ||
| 2 | <div class="hello"> | ||
| 3 | <h1>{{ msg }}</h1> | ||
| 4 | <p> | ||
| 5 | For a guide and recipes on how to configure / customize this project,<br /> | ||
| 6 | check out the | ||
| 7 | <a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>. | ||
| 8 | </p> | ||
| 9 | <h3>Installed CLI Plugins</h3> | ||
| 10 | <ul> | ||
| 11 | <li> | ||
| 12 | <a | ||
| 13 | href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" | ||
| 14 | target="_blank" | ||
| 15 | rel="noopener" | ||
| 16 | >babel</a | ||
| 17 | > | ||
| 18 | </li> | ||
| 19 | <li> | ||
| 20 | <a | ||
| 21 | href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" | ||
| 22 | target="_blank" | ||
| 23 | rel="noopener" | ||
| 24 | >eslint</a | ||
| 25 | > | ||
| 26 | </li> | ||
| 27 | </ul> | ||
| 28 | <h3>Essential Links</h3> | ||
| 29 | <ul> | ||
| 30 | <li> | ||
| 31 | <a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a> | ||
| 32 | </li> | ||
| 33 | <li> | ||
| 34 | <a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a> | ||
| 35 | </li> | ||
| 36 | <li> | ||
| 37 | <a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a> | ||
| 38 | </li> | ||
| 39 | <li> | ||
| 40 | <a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a> | ||
| 41 | </li> | ||
| 42 | <li> | ||
| 43 | <a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a> | ||
| 44 | </li> | ||
| 45 | </ul> | ||
| 46 | <h3>Ecosystem</h3> | ||
| 47 | <ul> | ||
| 48 | <li> | ||
| 49 | <a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a> | ||
| 50 | </li> | ||
| 51 | <li> | ||
| 52 | <a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a> | ||
| 53 | </li> | ||
| 54 | <li> | ||
| 55 | <a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a> | ||
| 56 | </li> | ||
| 57 | <li> | ||
| 58 | <a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a> | ||
| 59 | </li> | ||
| 60 | <li> | ||
| 61 | <a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a> | ||
| 62 | </li> | ||
| 63 | </ul> | ||
| 64 | </div> | ||
| 65 | </template> | ||
| 66 | |||
| 67 | <script> | ||
| 68 | export default { | ||
| 69 | name: 'HelloWorld', | ||
| 70 | props: { | ||
| 71 | msg: String | ||
| 72 | } | ||
| 73 | } | ||
| 74 | </script> | ||
| 75 | |||
| 76 | <!-- Add "scoped" attribute to limit CSS to this component only --> | ||
| 77 | <style scoped> | ||
| 78 | h3 { | ||
| 79 | margin: 40px 0 0; | ||
| 80 | } | ||
| 81 | ul { | ||
| 82 | list-style-type: none; | ||
| 83 | padding: 0; | ||
| 84 | } | ||
| 85 | li { | ||
| 86 | display: inline-block; | ||
| 87 | margin: 0 10px; | ||
| 88 | } | ||
| 89 | a { | ||
| 90 | color: #42b983; | ||
| 91 | } | ||
| 92 | </style> |
src/components/TabBar.vue
0 → 100644
| 1 | <template> | ||
| 2 | <div> | ||
| 3 | <van-tabbar fixed v-model="active" @change="onChange"> | ||
| 4 | <van-tabbar-item icon="home-o">首页</van-tabbar-item> | ||
| 5 | <van-tabbar-item icon="good-job-o">github</van-tabbar-item> | ||
| 6 | </van-tabbar> | ||
| 7 | </div> | ||
| 8 | </template> | ||
| 9 | |||
| 10 | <script> | ||
| 11 | import _ from 'lodash' | ||
| 12 | console.log(_.join(['a', 'b'], '~')) | ||
| 13 | export default { | ||
| 14 | name: 'TabBar', | ||
| 15 | data() { | ||
| 16 | return { | ||
| 17 | active: 0 | ||
| 18 | } | ||
| 19 | }, | ||
| 20 | methods: { | ||
| 21 | onChange(index) { | ||
| 22 | if (index === 1) window.location.href = 'https://github.com/sunniejs/vue-h5-template' | ||
| 23 | } | ||
| 24 | } | ||
| 25 | } | ||
| 26 | </script> | ||
| 27 | |||
| 28 | <!-- Add "scoped" attribute to limit CSS to this component only --> | ||
| 29 | <style scoped> | ||
| 30 | h3 { | ||
| 31 | margin: 40px 0 0; | ||
| 32 | } | ||
| 33 | ul { | ||
| 34 | list-style-type: none; | ||
| 35 | padding: 0; | ||
| 36 | } | ||
| 37 | li { | ||
| 38 | display: inline-block; | ||
| 39 | margin: 0 10px; | ||
| 40 | } | ||
| 41 | a { | ||
| 42 | color: #42b983; | ||
| 43 | } | ||
| 44 | </style> |
| ... | @@ -11,6 +11,15 @@ export const router = [ | ... | @@ -11,6 +11,15 @@ export const router = [ |
| 11 | title: '首页', // 页面标题 | 11 | title: '首页', // 页面标题 |
| 12 | keepAlive: false // keep-alive 标识 | 12 | keepAlive: false // keep-alive 标识 |
| 13 | } | 13 | } |
| 14 | }, | ||
| 15 | { | ||
| 16 | path: '/about', | ||
| 17 | name: 'about', | ||
| 18 | component: () => import('@/views/home/about'), | ||
| 19 | meta: { | ||
| 20 | title: '关于我', | ||
| 21 | keepAlive: false | ||
| 22 | } | ||
| 14 | } | 23 | } |
| 15 | ] | 24 | ] |
| 16 | 25 | ... | ... |
src/views/home/about.vue
0 → 100644
| 1 | <!-- home --> | ||
| 2 | <template> | ||
| 3 | <div class="app-container"> | ||
| 4 | <div class="warpper"> | ||
| 5 | <h1 class="demo-home__title"><img src="https://imgs.solui.cn/weapp/logo.png" /><span>VUE H5开发模板</span></h1> | ||
| 6 | <h2 class="demo-home__desc"> | ||
| 7 | A vue h5 template with Vant UI | ||
| 8 | </h2> | ||
| 9 | </div> | ||
| 10 | <van-cell icon="success" v-for="item in list" :key="item" :title="item" /> | ||
| 11 | <!-- tabbar --> | ||
| 12 | <TabBar></TabBar> | ||
| 13 | </div> | ||
| 14 | </template> | ||
| 15 | |||
| 16 | <script> | ||
| 17 | import TabBar from '@/components/TabBar' | ||
| 18 | // 请求接口 | ||
| 19 | import {getUserInfo} from '@/api/user.js' | ||
| 20 | |||
| 21 | export default { | ||
| 22 | components: { | ||
| 23 | TabBar | ||
| 24 | }, | ||
| 25 | |||
| 26 | data() { | ||
| 27 | return { | ||
| 28 | list: [ | ||
| 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 | } | ||
| 43 | }, | ||
| 44 | |||
| 45 | computed: {}, | ||
| 46 | |||
| 47 | mounted() { | ||
| 48 | this.initData() | ||
| 49 | }, | ||
| 50 | |||
| 51 | methods: { | ||
| 52 | // 请求数据案例 | ||
| 53 | initData() { | ||
| 54 | // 请求接口数据,仅作为展示,需要配置src->config下环境文件 | ||
| 55 | const params = {user: 'sunnie'} | ||
| 56 | getUserInfo(params) | ||
| 57 | .then(() => {}) | ||
| 58 | .catch(() => {}) | ||
| 59 | } | ||
| 60 | } | ||
| 61 | } | ||
| 62 | </script> | ||
| 63 | <style lang="scss" scoped> | ||
| 64 | .app-container { | ||
| 65 | .warpper { | ||
| 66 | padding: 12px; | ||
| 67 | .demo-home__title { | ||
| 68 | margin: 0 0 6px; | ||
| 69 | font-size: 32px; | ||
| 70 | .demo-home__title img, | ||
| 71 | .demo-home__title span { | ||
| 72 | display: inline-block; | ||
| 73 | vertical-align: middle; | ||
| 74 | } | ||
| 75 | img { | ||
| 76 | width: 32px; | ||
| 77 | } | ||
| 78 | span { | ||
| 79 | margin-left: 16px; | ||
| 80 | font-weight: 500; | ||
| 81 | } | ||
| 82 | } | ||
| 83 | .demo-home__desc { | ||
| 84 | margin: 0 0 20px; | ||
| 85 | color: rgba(69, 90, 100, 0.6); | ||
| 86 | font-size: 14px; | ||
| 87 | } | ||
| 88 | } | ||
| 89 | } | ||
| 90 | </style> |
| ... | @@ -8,22 +8,23 @@ | ... | @@ -8,22 +8,23 @@ |
| 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 | <van-tabbar fixed v-model="active" @change="onChange"> | 11 | <!-- tabbar --> |
| 12 | <van-tabbar-item icon="home-o">首页</van-tabbar-item> | 12 | <TabBar></TabBar> |
| 13 | <van-tabbar-item icon="good-job-o">github</van-tabbar-item> | ||
| 14 | </van-tabbar> | ||
| 15 | </div> | 13 | </div> |
| 16 | </template> | 14 | </template> |
| 17 | 15 | ||
| 18 | <script> | 16 | <script> |
| 17 | import TabBar from '@/components/TabBar' | ||
| 19 | // 请求接口 | 18 | // 请求接口 |
| 20 | import { getUserInfo } from '@/api/user.js' | 19 | import {getUserInfo} from '@/api/user.js' |
| 20 | |||
| 21 | export default { | 21 | export default { |
| 22 | components: {}, | 22 | components: { |
| 23 | TabBar | ||
| 24 | }, | ||
| 23 | 25 | ||
| 24 | data() { | 26 | data() { |
| 25 | return { | 27 | return { |
| 26 | active: 0, | ||
| 27 | list: [ | 28 | list: [ |
| 28 | 'Vue-cli4', | 29 | 'Vue-cli4', |
| 29 | 'VantUI组件按需加载', | 30 | 'VantUI组件按需加载', |
| ... | @@ -51,18 +52,16 @@ export default { | ... | @@ -51,18 +52,16 @@ export default { |
| 51 | // 请求数据案例 | 52 | // 请求数据案例 |
| 52 | initData() { | 53 | initData() { |
| 53 | // 请求接口数据,仅作为展示,需要配置src->config下环境文件 | 54 | // 请求接口数据,仅作为展示,需要配置src->config下环境文件 |
| 54 | const params = {user:'sunnie'} | 55 | const params = {user: 'sunnie'} |
| 55 | getUserInfo() | 56 | getUserInfo(params) |
| 56 | .then(() => { }) | 57 | .then(() => {}) |
| 57 | .catch(() => { }) | 58 | .catch(() => {}) |
| 58 | }, | ||
| 59 | onChange(index) { | ||
| 60 | if (index === 1) window.location.href = 'https://github.com/sunnie1992/vue-h5-template' | ||
| 61 | } | 59 | } |
| 62 | } | 60 | } |
| 63 | } | 61 | } |
| 64 | </script> | 62 | </script> |
| 65 | <style lang="scss" scoped> | 63 | <style lang="scss" scoped> |
| 64 | // @import '@/assets/css/index.scss'; | ||
| 66 | .app-container { | 65 | .app-container { |
| 67 | .warpper { | 66 | .warpper { |
| 68 | padding: 12px; | 67 | padding: 12px; | ... | ... |
| 1 | 'use strict' | 1 | 'use strict' |
| 2 | const path = require('path') | 2 | const path = require('path') |
| 3 | const defaultSettings = require('./src/config/index.js') | 3 | const defaultSettings = require('./src/config/index.js') |
| 4 | function resolve(dir) { | 4 | const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin |
| 5 | return path.join(__dirname, dir) | 5 | |
| 6 | } | 6 | const resolve = dir => path.join(__dirname, dir) |
| 7 | const name = defaultSettings.title || 'vue mobile template' // page title | 7 | // page title |
| 8 | const name = defaultSettings.title || 'vue mobile template' | ||
| 9 | const IS_PROD = ['production', 'prod'].includes(process.env.NODE_ENV) | ||
| 8 | 10 | ||
| 11 | // externals | ||
| 9 | const externals = { | 12 | const externals = { |
| 10 | vue: 'Vue', | 13 | vue: 'Vue', |
| 11 | 'vue-router': 'VueRouter', | 14 | 'vue-router': 'VueRouter', |
| ... | @@ -13,27 +16,39 @@ const externals = { | ... | @@ -13,27 +16,39 @@ const externals = { |
| 13 | vant: 'vant', | 16 | vant: 'vant', |
| 14 | axios: 'axios' | 17 | axios: 'axios' |
| 15 | } | 18 | } |
| 16 | // cdn | 19 | // CDN外链,会插入到index.html中 |
| 17 | const cdn = { | 20 | const cdn = { |
| 18 | // 开发环境 | 21 | // 开发环境 |
| 19 | dev: { | 22 | dev: { |
| 20 | css: [], | 23 | css: [ |
| 24 | ], | ||
| 21 | js: [] | 25 | js: [] |
| 22 | }, | 26 | }, |
| 23 | // 生产环境 | 27 | // 生产环境 |
| 24 | build: { | 28 | build: { |
| 25 | css: ['https://cdn.jsdelivr.net/npm/vant@beta/lib/index.css'], | 29 | css: ['https://cdn.jsdelivr.net/npm/vant@2.4.7/lib/index.css'], |
| 26 | js: [ | 30 | js: [ |
| 27 | 'https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js', | 31 | 'https://cdn.jsdelivr.net/npm/vue@2.6.11/dist/vue.min.js', |
| 28 | 'https://cdnjs.cloudflare.com/ajax/libs/vue-router/3.0.6/vue-router.min.js', | 32 | 'https://cdn.jsdelivr.net/npm/vue-router@3.1.5/dist/vue-router.min.js', |
| 29 | 'https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.min.js', | 33 | 'https://cdn.jsdelivr.net/npm/axios@0.19.2/dist/axios.min.js', |
| 30 | 'https://cdnjs.cloudflare.com/ajax/libs/vuex/3.1.1/vuex.min.js', | 34 | 'https://cdn.jsdelivr.net/npm/vuex@3.1.2/dist/vuex.min.js', |
| 31 | 'https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/crypto-js.min.js', | 35 | 'https://cdn.jsdelivr.net/npm/vant@2.4.7/lib/index.min.js' |
| 32 | 'https://cdn.jsdelivr.net/npm/vant@beta/lib/vant.min.js' | ||
| 33 | ] | 36 | ] |
| 34 | } | 37 | } |
| 35 | } | 38 | } |
| 36 | const IS_PROD = ['production', 'prod'].includes(process.env.NODE_ENV) | 39 | // const cdn = { |
| 40 | // css: ['https://cdn.jsdelivr.net/npm/vant@2.4.7/lib/index.css'], | ||
| 41 | // js: [ | ||
| 42 | // 'https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.min.js', | ||
| 43 | // 'https://cdnjs.cloudflare.com/ajax/libs/vue-router/3.1.5/vue-router.min.js', | ||
| 44 | // 'https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.2/axios.min.js', | ||
| 45 | // 'https://cdnjs.cloudflare.com/ajax/libs/vuex/3.1.2/vuex.min.js', | ||
| 46 | // 'https://cdn.jsdelivr.net/npm/vant@2.4.7/lib/index.min.js', | ||
| 47 | // 'https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/crypto-js.min.js', | ||
| 48 | |||
| 49 | // ] | ||
| 50 | // } | ||
| 51 | |||
| 37 | module.exports = { | 52 | module.exports = { |
| 38 | publicPath: './', // 署应用包时的基本 URL。 vue-router hash 模式使用 | 53 | publicPath: './', // 署应用包时的基本 URL。 vue-router hash 模式使用 |
| 39 | // publicPath: '/app/', //署应用包时的基本 URL。 vue-router history模式使用 | 54 | // publicPath: '/app/', //署应用包时的基本 URL。 vue-router history模式使用 |
| ... | @@ -48,7 +63,7 @@ module.exports = { | ... | @@ -48,7 +63,7 @@ module.exports = { |
| 48 | // 当出现编译器错误或警告时,在浏览器中显示全屏覆盖层 | 63 | // 当出现编译器错误或警告时,在浏览器中显示全屏覆盖层 |
| 49 | warnings: false, | 64 | warnings: false, |
| 50 | errors: true | 65 | errors: true |
| 51 | }, | 66 | } |
| 52 | // proxy: { | 67 | // proxy: { |
| 53 | // //配置跨域 | 68 | // //配置跨域 |
| 54 | // '/api': { | 69 | // '/api': { |
| ... | @@ -63,87 +78,99 @@ module.exports = { | ... | @@ -63,87 +78,99 @@ module.exports = { |
| 63 | }, | 78 | }, |
| 64 | 79 | ||
| 65 | configureWebpack: config => { | 80 | configureWebpack: config => { |
| 81 | config.name = name | ||
| 66 | // 为生产环境修改配置... | 82 | // 为生产环境修改配置... |
| 67 | if (process.env.NODE_ENV === 'production') { | 83 | if (IS_PROD) { |
| 68 | // externals里的模块不打包 | 84 | // externals |
| 69 | Object.assign(config, { | 85 | config.externals = externals |
| 70 | name: name, | ||
| 71 | externals: externals | ||
| 72 | }) | ||
| 73 | } | 86 | } |
| 74 | // 为开发环境修改配置... | 87 | // 为开发环境修改配置... |
| 75 | // if (process.env.NODE_ENV === 'development') { | 88 | // if (process.env.NODE_ENV === 'development') { |
| 76 | // } | 89 | // } |
| 77 | }, | 90 | }, |
| 78 | chainWebpack(config) { | 91 | |
| 92 | chainWebpack: config => { | ||
| 79 | config.plugins.delete('preload') // TODO: need test | 93 | config.plugins.delete('preload') // TODO: need test |
| 80 | config.plugins.delete('prefetch') // TODO: need test | 94 | config.plugins.delete('prefetch') // TODO: need test |
| 81 | // alias | 95 | |
| 96 | // 别名 alias | ||
| 82 | config.resolve.alias | 97 | config.resolve.alias |
| 83 | .set('@', resolve('src')) | 98 | .set('@', resolve('src')) |
| 84 | .set('assets', resolve('src/assets')) | 99 | .set('assets', resolve('src/assets')) |
| 85 | .set('api', resolve('src/api')) | 100 | .set('api', resolve('src/api')) |
| 86 | .set('views', resolve('src/views')) | 101 | .set('views', resolve('src/views')) |
| 87 | .set('components', resolve('src/components')) | 102 | .set('components', resolve('src/components')) |
| 88 | 103 | // 打包分析 | |
| 104 | if (IS_PROD) { | ||
| 105 | config.plugin('webpack-report').use(BundleAnalyzerPlugin, [ | ||
| 106 | { | ||
| 107 | analyzerMode: 'static' | ||
| 108 | } | ||
| 109 | ]) | ||
| 110 | } | ||
| 89 | /** | 111 | /** |
| 90 | * 添加CDN参数到htmlWebpackPlugin配置中, 详见public/index.html 修改 | 112 | * 添加CDN参数到htmlWebpackPlugin配置中 |
| 91 | */ | 113 | */ |
| 92 | config.plugin('html').tap(args => { | 114 | config.plugin('html').tap(args => { |
| 93 | if (process.env.NODE_ENV === 'production') { | 115 | if (IS_PROD) { |
| 94 | args[0].cdn = cdn.build | 116 | args[0].cdn = cdn.build |
| 95 | } | 117 | } else { |
| 96 | if (process.env.NODE_ENV === 'development') { | ||
| 97 | args[0].cdn = cdn.dev | 118 | args[0].cdn = cdn.dev |
| 98 | } | 119 | } |
| 120 | |||
| 99 | return args | 121 | return args |
| 100 | }) | 122 | }) |
| 101 | |||
| 102 | // set preserveWhitespace | 123 | // set preserveWhitespace |
| 103 | config.module | 124 | // config.module |
| 104 | .rule('vue') | 125 | // .rule('vue') |
| 105 | .use('vue-loader') | 126 | // .use('vue-loader') |
| 106 | .loader('vue-loader') | 127 | // .loader('vue-loader') |
| 107 | .tap(options => { | 128 | // .tap(options => { |
| 108 | options.compilerOptions.preserveWhitespace = true | 129 | // options.compilerOptions.preserveWhitespace = true |
| 109 | return options | 130 | // return options |
| 110 | }) | 131 | // }) |
| 111 | .end() | 132 | // .end() |
| 112 | 133 | ||
| 113 | config | 134 | // config |
| 114 | // https://webpack.js.org/configuration/devtool/#development | 135 | // // https://webpack.js.org/configuration/devtool/#development |
| 115 | .when(process.env.NODE_ENV === 'development', config => config.devtool('cheap-source-map')) | 136 | // .when(process.env.NODE_ENV === 'development', config => config.devtool('cheap-source-map')) |
| 116 | 137 | ||
| 117 | config.when(process.env.NODE_ENV !== 'development', config => { | 138 | // config.when(IS_PROD, config => { |
| 118 | config | 139 | // config |
| 119 | .plugin('ScriptExtHtmlWebpackPlugin') | 140 | // .plugin('ScriptExtHtmlWebpackPlugin') |
| 120 | .after('html') | 141 | // .after('html') |
| 121 | .use('script-ext-html-webpack-plugin', [ | 142 | // .use('script-ext-html-webpack-plugin', [ |
| 122 | { | 143 | // { |
| 123 | // `runtime` must same as runtimeChunk name. default is `runtime` | 144 | // // `runtime` must same as runtimeChunk name. default is `runtime` |
| 124 | inline: /runtime\..*\.js$/ | 145 | // inline: /runtime\..*\.js$/ |
| 125 | } | 146 | // } |
| 126 | ]) | 147 | // ]) |
| 127 | .end() | 148 | // .end() |
| 128 | config.optimization.splitChunks({ | 149 | // config.optimization.splitChunks({ |
| 129 | chunks: 'all', | 150 | // chunks: 'all', |
| 130 | cacheGroups: { | 151 | // cacheGroups: { |
| 131 | commons: { | 152 | // // cacheGroups 下可以可以配置多个组,每个组根据test设置条件,符合test条件的模块 |
| 132 | name: 'chunk-commons', | 153 | // commons: { |
| 133 | test: resolve('src/components'), // can customize your rules | 154 | // name: 'chunk-commons', |
| 134 | minChunks: 3, // minimum common number | 155 | // test: resolve('src/components'), |
| 135 | priority: 5, | 156 | // minChunks: 3, // 被至少用三次以上打包分离 |
| 136 | reuseExistingChunk: true | 157 | // priority: 5, // 优先级 |
| 137 | }, | 158 | // reuseExistingChunk: true // 复用其他chunk内已拥有的模块 |
| 138 | libs: { | 159 | // }, |
| 139 | name: 'chunk-libs', | 160 | // // vantUI: { |
| 140 | chunks: 'initial', // only package third parties that are initially dependent | 161 | // // name: 'chunk-vantUI', // 将 vant 打包到单独文件 |
| 141 | test: /[\\/]node_modules[\\/]/, | 162 | // // priority: 20, |
| 142 | priority: 10 | 163 | // // test: /[\\/]node_modules[\\/]_?vant(.*)/ // in order to adapt to cnpm |
| 143 | } | 164 | // // }, |
| 144 | } | 165 | // libs: { |
| 145 | }) | 166 | // name: 'chunk-libs', |
| 146 | config.optimization.runtimeChunk('single') | 167 | // chunks: 'initial', // only package third parties that are initially dependent |
| 147 | }) | 168 | // test: /[\\/]node_modules[\\/]/, |
| 169 | // priority: 10 | ||
| 170 | // } | ||
| 171 | // } | ||
| 172 | // }) | ||
| 173 | // config.optimization.runtimeChunk('single') | ||
| 174 | // }) | ||
| 148 | } | 175 | } |
| 149 | } | 176 | } | ... | ... |
-
Please register or sign in to post a comment