针对"详解vue-cli3多页应用改造",我们需要掌握以下几个方面:
-
Vue-cli3多页应用的原理和基本配置
-
多页应用架构演变及其对应实现(如何从单页应用改造为多页应用)
-
懒加载和代码分割的原理和应用
-
多语言和国际化的实现方式
-
基于Vuex的SPA应用改造为多页应用的实践
下面我们来详细讲解一下这个完整攻略吧:
一、Vue-cli3多页应用的原理和基本配置
为了转化为多页应用,我们需要对Vue-cli3进行一定的配置。首先需要在项目中添加多个entry points,以创建多页应用。通过多个entry points,每个页面可以有它独立的逻辑和代码结构。同时,这样优化单页应用也更容易实现。
手动创建多候选页的开销太大,我们可以使用一个简单的脚本来生成这些文件。如下图所示,脚本文件multi-page-shell.js,在项目根目录下新建一个multi-page文件夹作为entry points目录。multi-page-shell.js将每个entry point的相应文件如index.html、 main.js等,通过fs和lodash模块动态生成到对应的目录里。
const path = require('path');
const fs = require('fs');
const _ = require('lodash');
var entryDir = path.join(__dirname, '../src/entry');
var distDir = path.join(__dirname, '../dist');
var entryFiles = fs.readdirSync(entryDir);
const entryPoints = entryFiles.reduce((acc, file) => {
let [name, extension] = file.split('.');
if (!acc[name]) {
acc[name] = {
entry: path.join(entryDir, `${name}.js`),
template: path.join(entryDir, `${name}.html`),
filename: `${name}.html`,
chunks: ['vendors', 'manifest']
};
}else {
acc[name].entry = [acc[name].entry, path.join(entryDir, `${name}.js`)];
acc[name].chunks.push(name);
}
acc[name].chunks.push('common');
return acc;
}, {});
module.exports = {
pages: entryPoints,
chainWebpack: (config) => {
const TYPES = ['vue-modules', 'vue', 'normal-modules', 'normal'];
TYPES.forEach(type => addStyleResource(config.module.rule('scss').oneOf(type)));
}
};
function addStyleResource(rule) {
rule.use('style-resource')
.loader('style-resources-loader')
.options({
patterns: [
path.resolve(__dirname, '../src/stylesheet/mixin.scss'),
path.resolve(__dirname, '../src/stylesheet/variables.scss')
]
});
}
初始化的Vue CLI项目中包含了一个vue.config.js配置文件,我们需要在这个文件中添加pages属性,其值为一个对象,包含每一个entry point的配置。
在上面的脚本中,我们定义了一个entryDir变量。这是存放entry points的目录,它们的名字类似于“home”或“login”,而且带有html和js的扩展名。
在生成的每个entry point的对象中,我们至少需要指定两个属性:template和entry。这些属性控制着所渲染HTML文件的位置以及打包的JavaScript文件的相应位置。我们还可以指定新打包文件的名称和任何我们需要共享的代码块名称。
下面是一个典型的pages对象的例子:
module.exports = {
pages: {
home: {
// 登录页面的入口文件
entry: 'src/entry/home.js',
// 模板文件
template: 'src/entry/home.html',
// 输出文件名称
filename: 'home.html',
// anytime、anywhere
title: 'Home Page',
// 提取出来的通用 chunk 和 vendor chunk。
chunks: ['chunk-vendors', 'chunk-common', 'home']
},
login: {
// 登录页面的入口文件
entry: 'src/entry/login.js',
// 模板文件
template: 'src/entry/login.html',
// 输出文件名称
filename: 'login.html',
// anytime、anywhere
title: 'Login Page',
// 提取出来的通用 chunk 和 vendor chunk。
chunks: ['chunk-vendors', 'chunk-common', 'login']
},
}
}
以上配置让Vue Cli知道了我们要构建几个页面,各自的HTML文件名和对应的入口JavaScript文件路径。
二、多页应用架构演变及其对应实现
从单页应用改造为多页应用,我们需要思考架构和实现方面的问题。比如:有没有必要使用路由器?有没有必要引入state管理(如Vuex)?如何使用webpack实现构建的自动化?等等。
以下是多页应用开发的一些步骤:
-
构建Vue.js应用,并创建多个入口JavaScript文件。
-
配置webpack入口entry points。
-
根据每个entry point设置HTML模板文件,以及文件名、title属性和所需的script / link标记。
-
为每个entry point引入公共库,并将它们提取到公共块或vendor块中。
-
为每个entry point引入一些特定的库,并将它们提取到任何特定的块中。
-
将您的JavaScript代码分割成模块,以便在需要时按需加载。
-
优化代码,删除多余的依赖项和无用代码。并将最终编译的CSS、JS、图像和其他资产复制到适当的文件夹中。
示例一:
以一个简单的登录示例为例,使用Vue.js实现多页应用。登录页面,注册页面和首页都有自己的entry points并使用不同的HTML文件。
-
创建一个名为/usr/login.html的文件,并添加所需的html和script标记。
-
/usr/login.js文件内容如下:
import Vue from 'vue'
import App from '../views/Login.vue'
new Vue({
el: '#app',
render: h => h(App)
})
- 配置webpack以使其可以定位入口点并编译它们。
module.exports = {
mode: NODE_ENV || 'development',
entry: {
home: './src/entry/home.js',
login: './src/entry/login.js',
register: './src/entry/register.js'
},
output: {
path: path.join(__dirname, 'dist'),
filename: '[name].js'
}
};
示例二:
为一个移动端项目实现多页应用的架构演变,包含登录、注册、个人中心和设置等模块。其中登录和注册采用单页应用的方式,个人中心和设置采用多页应用的方式。
-
新增一个页面设置页面。
-
创建一个settings.html文件和一个settings.js文件,其中HTML文件至少包含根元素和一个脚本标记,而JavaScript文件应至少包含Vue.js实例的创建代码。
-
修改webpack配置文件以支持多个entry points。
module.exports = {
mode: NODE_ENV || 'development',
entry: {
home: './src/entry/home.js',
login: './src/entry/login.js',
register: './src/entry/register.js',
settings: './src/entry/settings.js'
},
output: {
path: path.join(__dirname, 'dist'),
filename: '[name].js'
}
};
以上的步骤可以帮助我们快速构建一个Vue Cli3多页应用,当然,想要在这个基础上构建出更加符合业务需求的应用,我们还需要结合实际情况进行调整和扩展。
三、懒加载和代码分割的原理和应用
懒加载和代码分割是Vue Cli3中优化多页应用的两个重要手段。懒加载(或按需加载)是指只有在内容被请求时才会被加载。而代码分割是指按照一个规则把代码划分成若干块,以便可以按需加载这些块并避免不必要的代码加载。
在多页应用中,我们可以根据业务逻辑把一些功能模块拆分成不同的模块,这样可以使得每个页面只加载自己需要的模块,从而大幅提升页面加载速度。使用webpack的动态导入(Dynamic Imports)API,我们可以动态地将组件打包生成新的chunk,比如:
const Foo = () => import(/* webpackChunkName: "group-foo" */ '@/views/Foo')
上面的代码只有当用户访问到/foo时才会加载Foo组件所在的chunk。
四、多语言和国际化的实现方式
多语言和国际化的实现涉及到一些复杂的逻辑,但是在Vue Cli3中,它们是非常方便的。
首先我们使用vue-i18n作为多语言处理的工具。在多页应用中,我们可以在每个entry point的Vue实例中单独引入vue-i18n。在每个.HTML文件中,我们可以在模板的根元素上添加lang属性来指定使用哪种语言版本。在一个简单的登录示例中,我们可能想要为英语和中文分别提供两个版本。如下所示:
<template>
<div>
<h2>{{ $t('login') }}</h2>
<form>
<input type="email" placeholder="{{ $t('email') }}">
<input type="password" placeholder="{{ $t('password') }}">
<div>{{$t('language')}}</div>
<div v-for="(m,i) in messages" :key="i">{{ $t('message.' + m.id) }}</div>
<div>
<button>{{ $t('login') }}</button>
<a href="">{{
$t('register')
}}</a>
</div>
</form>
</div>
</template>
在main.js中引入vue-i18n,如下所示:
import Vue from 'vue'
import VueI18n from 'vue-i18n'
import messages from './messages.json'
Vue.use(VueI18n)
const i18n = new VueI18n({
locale: 'en', // set locale
messages // set locale messages
})
new Vue({
el: '#app',
i18n,
render: h => h(App)
})
五、基于Vuex的SPA应用改造为多页应用的实践
Vuex是一个状态管理库,通常用于构建单页应用。但是,在某些情况下,我们可能希望在多页应用中使用Vuex。例如,如果多个页面都需要访问同一个API端点或共享用户登录状态,则状态应该与其他页面保持同步。
在多页应用中,我们必须在vue.config.js中将使用相同实例,否则每个页面都会被单独使用一个Vuex实例。
我们可以使用Vuex的subscribe函数将更改持久化到本地存储中。在每次窗口加载时,我们可以从本地存储中还原状态。示例代码如下:
import Vuex from 'vuex'
import createLogger from 'vuex/dist/logger' // 引入日志插件
import * as types from './mutation-types'
const debug = process.env.NODE_ENV !== 'production';
const store = new Vuex.Store({
modules: {
...
},
actions,
strict: debug,
plugins: debug ? [createLogger()] : [],
});
store.subscribe((mutation, state) => {
if (mutation.type === types.LOGIN_SUCCESS) {
localStorage.setItem('token', mutation.payload);
}
if (mutation.type === types.LOGOUT) {
localStorage.removeItem('token');
}
if (mutation.type === types.INIT) {
const token = localStorage.getItem('token');
if (token) {
const user = getUserByToken(token);
if (user) {
store.commit(types.LOGIN_SUCCESS, token);
store.commit(types.INIT, user);
store.dispatch('fetchWordCloudData');
}
}
}
});
我们可以在每个entry point中集成Vuex,并在相应的HTML文件中单独初始化。在app.js中,我们可以通用的初始化Vuex,并将其传递给所有entry point。
import Vue from 'vue'
import Vuex from 'vuex'
import App from './App.vue'
import store from './store'
import router from './router'
Vue.use(Vuex)
new Vue({
store,
router,
render: h => h(App)
}).$mount('#app')
以上是基于Vue Cli3实现多页应用的攻略详解,如果还有不懂的地方,欢迎大家一起讨论交流。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:详解vue-cli3多页应用改造 - Python技术站