之前分享过在使用Vue-cli的时候怎么构建多页应用,如今随着Vite这样一个轻量级易用的构建工具的出现,越来越多的人也去尝试Vite了。在Vue-cli迁移到Vite的过程中,多多少少会有一些问题,多页应用的配置就是其中之一。
1,认识Vite项目中页面加载和根组件挂载过程
事实上,Vite项目中根组件加载过程和Vue-cli是差不多的,只不过目录结构有点小变化。
上述目录和文件:
- 1.vscode项目配置
- 2.nodejs项目依赖库文件,平时需要加入
.gitignore - 3.公共文件夹
- 4.源码文件夹
- 4.1.存放静态资源例如图片、音频等等
- 4.2.存放Vue组件
- 4.3.Vue根组件,这个大家应该很熟悉
- 4.4. 入口文件,大家也耳熟能详了
-
- Git忽略文件
-
- 主页面模板文件
-
- 依赖配置文件,里面记录了依赖库
-
README文件
-
- Vite项目的配置文件,和Vue-cli中的
vue.config.js是一个作用
- Vite项目的配置文件,和Vue-cli中的
可见,对比起Vue-cli项目,最大的不同就是原先在public文件夹中的index.html,现在是在项目根目录了!
(1) Vite项目中路径和网站访问路径的对应关系
首先我们要引入一个概念:根路径。在Vite工程中,默认情况下根路径就是我们的项目目录,即src文件夹所在的那个目录(注意是所在),在Vite中用/表示根路径。因此在这里/开头的路径就是绝对路径。
通过在配置文件中指定root配置项的值可以自定义根路径的位置,不过平时可以不用修改。
那么在Vite中,我们的根组件又是如何被加载的呢?
在Vite工程中,当我们访问网站根路径的时候,事实上会访问到我们项目根路径上的index.html文件。
没错,在Vite工程中,预览网页时访问网站的网址路径和我们工程路径是对应的。
我们的Vite工程启动后,访问http://localhost:3000/,也就是访问我们的网址根路径的时候,Vite就会去项目中寻找/index.html并返回,也就是说我们会访问到我们项目中的/index.html上。
同样地:
- 访问
http://localhost:3000/test/,Vite就会去项目目录中寻找/test/index.html并返回,即我们访问到的是/test/index.html文件 - 访问
http://localhost:3000/test/page/,Vite就会去项目目录中寻找/test/page/index.html并返回,即我们访问到的是/test/page/index.html文件
可见,我们访问网页路径的时候,和项目路径是一一对应的,这和大多数静态服务器一样。
同样地,在Vite中还有base配置项,这个配置项其实就和Vue-cli的publicPath是一个意思,就是开发或生产环境服务的公共基础路径,其默认值是/。
通俗地讲,这个配置项表示我们外部访问的根路径是什么,也就是说我们在外部通过网址访问时访问什么路径,Vite就会去根路径寻找index.html。
其默认值是/,也就是说正如上面讲的一样,我们访问网站根路径的时候,Vite就会让我们访问到项目根路径的index.html上面。
以此类推就很简单了,如果我们配置base值为/path,那当我们访问http://localhost:3000/path/的时候,Vite才会去项目根路径找到index.html并返回。
当我们配置base值为/path时,同样地:
- 访问
http://localhost:3000/path/test/,Vite就会去项目目录中寻找/test/index.html并返回,即我们访问到的是/test/index.html文件 - 访问
http://localhost:3000/path/test/page/,Vite就会去项目目录中寻找/test/page/index.html并返回,即我们访问到的是/test/page/index.html文件
(2) 根组件挂载
根组件的挂载和Vue-cli项目几乎一模一样,我们还是来看一下入口文件/src/main.js文件:
import { createApp } from 'vue';
// 引入根组件
import App from './App.vue';
// 创建根组件实例并挂载至html文件中
createApp(App).mount('#app');
重点仍然在于createApp这个函数,先是引入组件模板,然后通过createApp函数,会返回一个提供应用上下文的应用实例,可以链式调用。
通俗地讲,先开始只是引入了Vue模板,但是仅仅引入模板,是不能将它和我们的html联系起来的。
通过createApp,我们才创建了一个可以供上下文使用的实例,也就是说只有这个函数,才能创建一个可以显示渲染的实例。
同样地,
createApp函数后面也可以链式调用use函数引入其它插件。
最后通过mount函数,把这个实例内容,即App.vue文件的内容挂载至网页某个节点上,这样才能显示。
那为什么要挂载到id为app的节点上呢?可以打开/index.html文件看看:
可见当我们访问网页根路径时,我们就访问了index.html这个网页,这时main.js被执行,其中createApp函数执行,并将App.vue的内容挂载(填充)至这个html的id为app的div中。
这里App.vue的内容如下:
访问网页,查看f12看看渲染结果:
可见通过main.js,把App.vue中的内容挂载到了html文件中id为app的节点下。
相信大家现在知道了Vite项目中,访问路径与项目路径的对应关系,以及一个页面的加载过程,知道了这些,配置出一个多页应用也是很简单的。
2,多页应用配置
同样地,多页应用中每一个页面也需要有它自己的html文件和入口js文件。
假设我这里要配置两个子页面,我们可以先在项目根目录下创建两个文件夹存放两个子页面的html文件和入口js文件。我这里创建两个文件夹pageone和pagetwo,并将/index.html和/src/main.js各复制一份到这两个文件夹:
每个子页面的入口js文件可以改名,但是html就不要改名了!保持index.html即可,否则访问时会导致找不到文件。
可见我这里子页面1对应的入口文件是/pageone/pageone.js,对应的html是/pageone/index.html;子页面2对应的入口文件是/pagetwo/pagetwo.js,对应的html是/pagetwo/index.html。
然后我们在src文件夹中新建page文件夹专门用于存放所有子页面的vue根组件及其子组件文件,在page中给每个页面创建个文件夹,并在文件夹中创建每个页面的根组件文件,如下:
可见每个子页面的组件都放在/src/page中的一个文件夹中,便于管理。
上述子页面1和子页面2的根组件分别是PageOne.vue和PageTwo.vue,两个文件内容如下:
不过这里为什么要把vue文件和入口文件与html文件分开放呢?放一起不更方便吗?
这里我觉得:
- Vite项目中
src目录基本上存放的绝大多数都是vue组件文件,两者分开会使得结构清晰 - 若把
html和入口文件也放在src中,访问子页面的时候路径会很长,打包后也很难对应
当然,这里也只是我的看法,大家可以根据自己的习惯进行组织,多页应用的配置的目录并非是死的,毕竟知道了页面加载的方式,我们也很容易配置多页应用了!
好了,现在修改每个页面的html文件和入口文件,这里先修改子页面1的html文件,打开/pageone/index.html文件,找到script标签,把里面的src属性值改成子页面1对应的入口文件路径,也就是说让子页面1的html文件链接上其入口文件:
注意这里src必须使用绝对路径!也就是/开头的路径,使用相对路径会导致无法加载。
然后修改子页面1的入口文件,打开/pageone/pageone.js文件,import组件的部分改成引入子页面1对应的Vue组件文件的路径:
好了,到此页面1就配置完成了!页面2也是同理。
然后就可以访问我们的多页应用了!
启动项目,访问http://localhost:3000/,如下:
访问http://localhost:3000/pageone/,如下:
访问http://localhost:3000/pagetwo/,如下:
注意在这里预览页面时,网址路径末尾必须以/结尾!否则也会导致找不到页面。
可见配置多页应用还是很简单的,如果仅仅是开发预览时配置多页应用,连配置文件都不用改。
3,多页应用打包
上述配置好多页应用之后,如果你这时执行打包构建命令,你会发现子页面文件并没有被包含到打包的结果中,因此我们还需要在配置文件中,配置一下打包解析,把每个子页面的html文件添加到打包解析中。
打开Vite配置文件vite.config.js,在其中进行打包解析配置。
先在配置文件中import一下resolve函数:
import { resolve } from 'path';
然后加入以下配置内容:
build: {
rollupOptions: {
input: {
// 配置所有页面路径,使得所有页面都会被打包
main: resolve(__dirname, 'index.html'),
pageone: resolve(__dirname, 'pageone/index.html'),
pagetwo: resolve(__dirname, 'pagetwo/index.html')
}
}
}
最终配置文件如下:
可见在上述的input中,配置一下每个页面的html文件解析路径即可!其中input对象里面,属性名可以自定义,属性值则是要解析的页面路径,通过resolve函数。
resolve函数的参数是填入多个路径,最终这个函数会把路径拼接起来。__dirname表示的是vite.config.js这个文件所在的路径。
在这里vite.config.js位于/,因此__dirname的值就是/,对于上述resolve(__dirname, 'pagetwo/index.html'),最终拼接出来的路径就是/pagetwo/index.html,这样就成功地找到了子页面2的html文件,打包的时候就会被包含。
需要注意的是,__dirname表示的是vite.config.js这个文件本身所在的路径而不是根路径! 因此即使你修改了配置项root为别的值,即你修改了根路径位置,这个__dirname的值仍然是vite.config.js这个文件所在的路径,这里需要注意一下。
再次执行打包命令npm run build,发现所有页面都被包含了:
同样地,如果配置了多页应用,就不能够把base配置为相对路径./了!否则会出现问题。
4,配置打包后页面文件到后端服务器
dist文件夹中的内容就可以放到后端服务器中去了!这里以Spring Boot为例,我们把dist文件夹中所有内容放到Spring Boot工程的src/main/resources/static目录下,即Spring Boot项目默认的静态资源目录下:
Spring Boot默认端口是8080,启动项目,访问http://127.0.0.1:8080/index.html,如下:
访问http://127.0.0.1:8080/pageone/index.html,如下:
访问http://127.0.0.1:8080/pagetwo/index.html,如下:
可见打包后配置到后端访问路径是和Vite开发预览时的是不一样的,这里注意即可,后端配置打包后的静态页面,访问路径就必须指定到具体的html文件上。
同样地,如果觉得访问路径太长或者不好看,也可以在Spring Boot中自定义Controller类进行自定义路由,这都是Spring Boot方面的内容了!这里就不再过多赘述,相信后端同学都能够信手拈来。
参考:
- Vite多页面应用:cn.vitejs.dev/guide/build…
- Vite基本配置:cn.vitejs.dev/config/#roo…