不只懂 Vue 语法:请说明 Vue CLI 的目录架构?

问题回答

开发时主要在 src 资料夹进行开发,最後打包输出时是 dist 资料夹。在 src 里,一定会用到 assets, components, views 以及 main.js 档案。assets 用作放静态资源,components 放元件,views 放页面元件,而 main.js 则是整个应用程序的进入点,意思是需要经 Webpack 编译的档案都需要在这里引入。

此篇文章我会使用 Vue CLI 创建档案,并设定加入 ESLint、 CSS 预处理器、Vue router、Vuex 来作说明。

Vue CLI 的目录架构

为了缩短篇幅,此图没显示 gitignorebabelnode_modufles 等档案和资料夹。

public 与 src/assets 资料夹的分别

src/assets 资料夹

  • 使用相对路径引入资源。例如:<img src="./assets/logo.png">
  • 官方建议把静态资源放在 src/assets 里。例如是图片、字型等等。
  • 所有在 src 里的资源都会经由 Webpack 编译。因此有以下好处:
    • 资源和程序档案都会被压缩和打包在一起,减少额外的网络请求。
    • 如果在开发时,有缺少载入任何档案,Vue CLI 会在编译时报错,而非等到用浏览器浏览时才出现 404 错误。
    • 避免因为浏览器的快取机制,导致用户只会看到旧版本的网页。因为 Webpack 最终打包後的文件名称会带 hash,强制浏览器执行最新的程序档案,因此不存在此问题。

最後一点也真的很方便!有时候改了一些样式,但因为档名没更动过,因此浏览器会以为没有什麽更动,因而继续显示缓存的档案。所以,常听说有些做法是在档案名称後加 timestamp 来强制浏览器更新。但如果用了 Webpack,因为输出的档案名称会带 hash,因此就能放心了,不用再用在档案名上加 timestamp 之类的手法。

public 资料夹

  • 当你要引用放在 public 资料夹里的资料,就需要使用绝对路径。这涉及到你部署的 domain 是否在根路径,这个之後会再谈及。
  • 放静态资源。包括 index.html 以及 favicon。虽然如此,但官方建议把静态资源放在 src/assets 里。
  • 在这资料夹里的资源大多不会经过 Webpack 编译。但注意,有些情况还是会由 Webpack 去做编译,例如:
    • 以上提到 index.html 会被 webpack 相关的套件去处理。
    • 当我们使用相对路径在 JavaScript、CSS 或 .vue 档案引入任何静态资源,它们都会被 Webpack 编译,并被视为该 module 的依赖。

例外情况

所以,大部分情况是建议把静态资源放在 src/assets 里,但官方网站也有提到一些需要用到 public 的原因,例如函式库与 webpack 不相容。

另一个比较明显的例子是,这篇文章有提到,假设我要用 v-html 来显示放在 src/assets 里的 logo.png,并在 DOM 里塞入 <img src="../assets/logo.png"> 这样的内容来引入 logo.png,最後是无法显示图片,因为输出时会直接当成字串输出 ../assets/logo.png,没有经过编译,因此并非正确路径。解决方法是我们需要在 public 引入 logo.png

详细完整示范:https://codesandbox.io/s/vue-cli-ru-he-yong-v-html-xian-shi-tu-pian-50rn1?file=/src/App.vue

components 与 views 的分别

components 是放元件,views 是放页面元件。一个页面元件上会由多个元件组成。

https://example.com/#/products 这个 products 页面为例。已知我们一定会有一个叫 Products.vue 作为页面元件。假如在此页面上,顶部有一个 swiper 轮播图片,下方是一个个卡片来显示每个产品。这情况可能就会出现两个档案,Swiper.vueProductCard.vue

src/
    components/
        Swiper.vue
        ProductCard.vue
    views/
        Products.vue   

router、store

在建立 Vue CLI 时,可以选择加入 Vue router 和 Vuex,前者会建立一个 router 资料夹,後者则是 store 资料夹,并且会自动在 main.js 引入这些资料夹。

App.vue

App.vue 是根元件。所有元件都会挂载在这个元件上。当我们切换页面,其实就是在 App.vue 此根元件里切换显示不同元件。

应用程序的进入点 main.js

main.js 是我们整个应用程序的进入点。把所有此应用程序用到的模组全都 import 进去 main.js。之後 webpack 就会编译这个档案,输出浏览器看得懂的档案。概念如下:

图片来源:https://webpack.js.org/

因为浏览器只看懂 HTML、CSS 和 JavaScript 档案,看不懂 .vue.scss 这些档案,所以需要透过 Webpack 此工具去编译,输出 HTML、CSS 和 JavaScript 档案。

注意,所有在 main.js 引入以及有关连的档案,才会被 webpack 编译。

补充一点,因为 Vue 预设是 SPA 框架,所以只会有一个进入点档案(main.js)。但如果想使用 MPA(多页式应用),就需要我们自己建立其他进入点档案。例如建立一个 product.js (进入点档案),以及 product.html (页面档案)。之後在 vue.config.js 再做相关的设定,详细可参考 Kuro 大大这篇的文章说明。

打包後会产生 dist 资料夹

所谓打包,透过在终端机输入 npm run build 指令,以 webpack 编译,最後输出 HTML、CSS 和 JavaScript 档案,并被放在 dist 资料夹里:

如果是静态应用程序,例如此专案只是串接公共 API ,我们只需把此 dist 资料夹部署到 GitHub Pages、Netlify 等静态网页托管服务上。以下用部署到 GitHub Pages 作为例子。

  1. 需要设定 publicPath。

因为 Vue Cli 预设你所部署的 domain 是在根路径'/',例如 https://my-vue-app.com/。如果是在子路径,例如 https://github.com/alysachan830/my-vue-app/#/,就要设定 publicPath/my-vue-app/

如果你是使用 Vue 3,做法就是在根目录建立 vue.config.js,内容如下:

module.exports = {
    publicPath: process.env.NODE_ENV === 'production'
      ? '/my-vue-app/'
      : '/'
}

以上做法能够在打包後,使 dist 里的index.html里所载入的js、css档案路径都改回正确的相对路径

  1. 最後,cd 到 dist 档案并进行git init、add、commit,之後推到gh-pages分支

以下的资源详细说明了以上步骤。

关於 vue.config.js的设定可看这篇:
https://tzuhui.github.io/2020/03/02/Vue/Vue-CLI3-to-github-pages/

原因细节可参考这个影片:
https://www.youtube.com/watch?v=njlABvVRB68&ab_channel=%E5%85%AD%E8%A7%92%E5%AD%B8%E9%99%A2

(大概54:25开始)

关於第 2 点的流程,可看这篇:
https://hsiangfeng.github.io/vue/20190513/948497494/

此外,如果是需要与後端程序做串接,就把此 dist 资料夹放到後端的服务器资料夹里,并把路由指向 dist 资料夹中 index.html 的位置,最後由後端处理部署。如果是用 Express.js 作为後端框架,可参考这篇文章,示范如何设定後端路由来连接 Vue。

总结

  • 把静态资源放在 public 资料夹,它们不会被 Webpack 编译(除非在其他档案有使用 import 引入这些资源)。
  • 引用静态资源时,需留意你之後部署此应用程序的 domin 是否在根路径。若不是,就要设定 publicPath
  • App.vue 是根元件,所有元件都会挂载在它上面。
  • main.js 是整个 Vue 应用程序的进入点档案,所有在此档案引入的资源以及有关连的档案,都会被 Vue 使用 Webpack 来进行编译。
  • 使用 npm run build 来进行编译,最後会输出 dist 资料夹以及 HTML、CSS、JavaScript 档案。因为浏览器只能读取这三种档案,所以需要进行以上提到的编译动作。

参考资料

How to Structure a Large Scale Vue.js Application
Vue CLI 环境设定与打包部署
How To Develop and Build Vue.js App With NodeJS
Vue 2.x & Vue CLI 3 配置与静态档引用路径


<<:  铁人赛 Day13 -- 一定要知道的JQuery (一) -- Click点击关闭盖板广告

>>:  Day1 写程序的前置工作!

Day26 NiFi 场景应用范例 (一)

今天开始会有两天来介绍简单的应用场景,会建置完整的 NiFi Data Pipeline 来让大家知...

Computed vs Methods

昨天已经把JSON档建置好了!今天就可以取用JSON档的资料然後实作出Methods和Compute...

Day11- pandas(6)DataFrame有效率的检视资料方法

往往我们在拿到一份资料时,数据都是很大很恐怖的 而且我们并无足够的时间将每个数值好好得看过一遍 pa...

DAY 12 SASS 间的相似之处

介绍完了前几天的 sass 各种用法,大家有没有觉得有些方法好像很类似? 像是 mixin 跟 ex...

用 Python 畅玩 Line bot - 30:Line Notify(三)

在上篇中,我们是需要到 Line Notify 登入後的个人介面发行 token,但总不能叫每一个加...