vue-router如何去中心化
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vue-router如何去中心化相关的知识,希望对你有一定的参考价值。
参考技术A
按照vue-router官方的使用文档中,我们在配置和使用vue-router的姿势如下:
ok,现在我们就可以在我们的组件中通过this.$route来操作路由相关属性及方法了。简直so easy!
何为中心化?
谈到中心化,我们想到比较多的可能就是区块链。那广义上的中心化如何理解?简单点说,就是在一个体系中某个节点要和另外的节点产生联系,就一定要通过特定的某个节点,这个节点就是一个中心。
vue-router的中心化
刚讲到中心化的概念,那我们可以拿上面vue-router实践的例子来对照一下。 我们在router/index.js中定义或加载所有的路由配置,那这个文件就是这个项目当中唯一的引用路由的节点(中心)。那中心节点会存在什么问题呢?
下面我们用一个比较简单的发布模型来说明。
模拟开发场景:
如何解决
1. 模块化
可以将路由按业务模块划分场景,对应模块下有一个独立的入口文件,尽可能保证相同业务需求不会出现路由文件冲突的情况。
对应的加载路由的配置可以修改为
2. require.context
官方文档的说明是require.context使用 directory 路径、includeSubdirs 选项和 filter 来指定一系列完整的依赖关系,便于更细粒度的控制模块引入。
文档地址:https://webpack.js.org/guides/dependency-management/#requirecontext
简单来说,通过require.context我们可以通过正则动态匹配并引入我们的依赖文件,这样我们不需要显示的去加载我们的路由文件,从而解耦router的入口文件和对应route配置的依赖关系。在这里我们通过它来实现我们的路由去中心化。
我们约定router目录下所有的.js文件默认都为route的配置文件,通过require.context加载的代码如下。
这样,以后新增或修改路由只需要按照约定在router目录新建js文件或修改其中的配置即可,router/index.js不需要任何改动即可完成路由配置。
总结
在这里我们总结下对于上述问题的一个解决思路,我们可以把中心化问题看成是一个依赖解耦的问题。那我们便可以用解耦的思路来解决中心化的问题,在上述解决方案中,我们用到了以下手段:
关于解耦的问题,我觉得也是一个可以好好讨论的点,有时间再和大家一起分享分享啦!感谢各位百忙之中抽出时间观看!!!
webpack 构建多页面应用初探
如何使用webpack构建多页面应用,这是一个我一直在想和解决的问题。网上也给出了很多的例子,很多想法。猛一看,觉得有那么点儿意思,但仔细看也就那样。
使用webpack这个构建工具,可以使我们少考虑很多的问题。
我们常见的单页面应用只有一个页面,它考虑问题,解决问题围绕着中心化去解决,因此很多麻烦都迎刃而解。如果你使用过vue.js,那么想必你一定用过vue-router,vuex,它们就是典型的中心化管理模式,当然还有很多,这里不一一列举了。
而多页面应用,我们不能再按照中心化模式的路走了,因为行不通,这也是很多人认为多页面应用不好做,或者干脆认为webapck只能做单页面应用,而不能做多页面应用的原因。
所以,我要说明的第一点儿是:不要用做单页面应用的思维来做多页面应用。
单页面中的模块共享和多页面的模块共享的区别
单页面的模块共享,其实是代码块在同一个页面的不同位置的重复出现;而多页面应用的代码块儿共享需要实现的不仅是同一个页面的共享,还要做到跨页面的共享。
所以,第一个要解决的问题是:不同页面的代码块共享如何实现?
单页面的路由管理,其实是根据用户的触发条件来实现不同的代码块的显隐;而多页面应用的路由管理则不然,它实现的是页面的跳转。
所以,第二个要解决的问题是:所页面应用的导航该如何做?
单页面的状态管理,很受开发者喜好。单页面是一个页面,所以页面中的数据状态的管理操作起来还算得心应手,那么多页面应用的呢,显然依靠它自身很难实现。
所以,第三个要解决的问题是:多页面应用的状态管理如何做?
注:这个问题问的其实有点儿傻,如果你做的是dom操作的多页面儿应用,就不用做状态管理了。如果你还是使用想vue.js这样的库,你就需要考虑要不要再用做多页面的状态管理了,因为此法儿就是为单页面应用做的,多页面儿行不通。
资源网站大全 https://55wd.com 我的007办公资源网站 https://www.wode007.com
多页面应用的探索
入口(entry):
webpack对入口不仅可以定义单个文件,也可以定义多个文件。
熟悉当页面应用开发的对于下面的代码应该不会陌生吧?
module.exports = { entry: ‘./src/index.js‘, ··· }
我第一次接触真正的单页面应用项目使用的就是angualrjs,使用的构建工具使webapck+gulp,其中的webpack.config.js中的看到的入口文件代码就是它。
后来,接触到的是数组形式,代码如下:
module.exports = { entry: [‘./src/index.js‘, ‘bootstrap‘] ··· }
这样,将bootstrap和入口文件一起引用,就可以在任何一个代码块中使用boostrap。
再后来,接触到的是对象形式,代码如下:
module.exports = { main: ‘./src/index.js‘ ··· }
这样做的目的是为了给输出的文件指定特定的名字。
再后来,就是做多页面应用,就需要用到如下的代码:
module.exports = { entry: { index: ‘./src/index.js‘, aboutUs: ‘./src/aboutus.js‘, contactUs: ‘./src/contactus.js‘ } }
为了引入第三方库,我们可以像如下这样做:
module.exports = { entry: { index: [‘./src/index.js‘, ‘loadsh‘], aboutUs: ‘./src/aboutus.js‘, contactUs: [‘./src/contactus.js‘, ‘lodash‘] } }
webpack3.x的探索
但为了共享模块代码,我们需要像下面这这样做:
const CommonsChunkPlugin = require(‘webpack‘).optimization.CommonsChunkPlugin module.exports = { entry: { index: [‘./src/index.js‘, ‘./src/utils/load.js‘, ‘loadsh‘], aboutUs: [‘./src/aboutus.js‘, ‘loadsh‘], contactUs: [‘./src/contactus.js‘,‘./src/utils/load.js‘, ‘lodash‘] }, plugins: [ new CommonsChunkPlugin({ name: "commons", filename: "commons.js", chunks: ["index", "aboutUs", "contactUs"] }) ] }
这样型就会形成如下所示的项目目录结构:
├── src
│ ├── common // 公用的模块
│ │ ├── a.js
│ │ ├── b.js
│ │ ├── c.js
│ │ ├── d.js
│ ├── uttils // 工具
│ │ ├── load.js // 工具代码load.js
│ ├── index.js // 主模块index.js (包含a.js, b.js, c.js, d.js)
│ ├── aboutUs.js // 主模块aboutus.js (包含a.js, b.js)
│ ├── contactUs.js // 主模块contactus.js (包含a.js, c.js)
├── webpack.config.js // css js 和图片资源
├── package.json
├── yarn.lock
但是这个内置插件的局限性比较大。正如上面所使用的那样,它只会提取chunks选项所匹配的模块共有的代码块。就如同上面代码表示的那样,它只会提取pindex, aboutUs, contactUs共有的代码块loadsh,而不会提取index, contactUs共有的代码块load.js。
当然,一般的第三方库,我们也不这样使用,而是像下面这样使用:
const CommonsChunkPlugin = require(‘webpack‘).optimization.CommonsChunkPlugin module.exports = { entry: { index: [‘./src/index.js‘, ‘./src/utils/load.js‘], aboutUs: [‘./src/aboutus.js‘], contactUs: [‘./src/contactus.js‘,‘./src/utils/load.js‘], vendors: [‘lodash‘] }, externals: { commonjs: "lodash", root: "_" }, plugins: [ new CommonsChunkPlugin({ name: "commons", filename: "commons.js", chunks: ["index", "aboutUs", "contactUs"] }) ] }
对于web应用最终的目的是:匹配生成不同的html页面。
这里我们要使用的就是html-webpack-plugin。
首先,需要安装html-webpack-plugin:
yarn add --dev html-webpack-plugin
然后引入插件,并配置如下:
... const htmlWebapckPlugin = require(‘html-webpack-plugin‘); ... plugins: [ ... new htmlWebapckPlugin({ filename: ‘index.html‘, chunks: [‘vendors‘, ‘commons‘, ‘index‘] }), new htmlWebapckPlugin({ filename: ‘aboutUs.html‘, chunks: [‘vendors‘, ‘commons‘, ‘aboutUs‘] }), new HtmlWebapckPlugin({ filename: ‘contactUs.html‘, chunks: [‘commons‘, ‘contactUs‘] }) ], ...
这样一个基于webpack3.x的多页面框架就有了基本的样子。
webpack4.x的探索
而使用webpack4.x则完全不同,它移除了内置的CommonsChunkPlugin插件,引入了SplitChunksPlugin插件,这个插件满足了我们的需要,弥补了CommonsChunkPlugin的不足。
如果你想要解决之前的不足,去提取index, contacUs共有的模块,操作起来会很简单。正如上面的所列举的那样,我们有三个入口点index, aboutUs, contactUs,SplitChunksPlugin 插件会首先获取这三个入口点共有的代码块,然后建立一个文件,紧接着获取每两个入口点的共有代码块,然后将每个入口点独有的代码块单独形成一个文件。如果你使用了第三方库,就像上面我们使用的loadsh,它会将第三方入口代码块单独打包为一个文件。
配置文件webpack.config.js需要增加如下的代码:
··· optimization: { splitChunks: { chunks: ‘all‘, maxInitialRequests: 20, maxAsyncRequests: 20, minSize: 40 } } ···
因为SplitChunksPlugin可以提取任意的入口点之间的共同代码,所以,我们就不需要使用vendors入口节点了。那么,为匹配生成不同的页面代码可以修改成如下:
const HtmlWebapckPlugin = require(‘html-webpack-plugin‘) ··· plugins: [ new HtmlWebapckPlugin({ filename: ‘index.html‘, chunks: [‘index‘] }), new HtmlWebapckPlugin({ filename: ‘aboutUs.html‘, chunks: [‘aboutUs‘] }), new HtmlWebapckPlugin({ filename: ‘contactUs.html‘, chunks: [‘contactUs‘] }), ] ···
可以发现结果越来越接近我们所想。但是这里还是存在一个问题,第三方库loadsh因为在入口点index, aboutUs中被分别引入,但是构建的结果却输出了两个第三方库文件,这不是我们想要的。这个问题怎么解决呢,因为html-webpack-plugin插件的chunks选项,支持多入口节点,所以,我们可以再单独创建一个第三方库的入口节点vendors。配置代码修改如下:
... entry: { index: [‘./src/index.js‘, ‘./src/utils/load.js‘], aboutUs: [‘./src/aboutUs.js‘], contactUs: [‘./src/contactUs.js‘,‘./src/utils/load.js‘], vendors: [‘loadsh‘] }, ... plugins: [ new HtmlWebapckPlugin({ filename: ‘index.html‘, chunks: [‘index‘, ‘vendors‘] }), new HtmlWebapckPlugin({ filename: ‘aboutUs.html‘, chunks: [‘aboutUs‘, ‘vendors‘] }), new HtmlWebapckPlugin({ filename: ‘contactUs.html‘, chunks: [‘contactUs‘] }), ], ...
注意:如果不同的入口点儿之间有依赖关系,如上面的index和vendors之间,因为index依赖于vendors,所以vendors要置于index之前。
这篇文章,说到这里基本上已经结束了。当然,webpack多页面应用的知识点还没有讲完,这些内容会放在后续的文章中详解。
以上是关于vue-router如何去中心化的主要内容,如果未能解决你的问题,请参考以下文章