首页 > 其他分享 >多页面应用(MPA)开发最佳实践

多页面应用(MPA)开发最佳实践

时间:2023-08-23 11:36:56浏览次数:38  
标签:index MPA app js 最佳 webpack html src 页面

缘由

平常开发当中,一般使用vue-cli2或vue-cli3脚手架来进行开发,默认构建出来的应用是单页面应用程序(SPA)。 面对一个工程下面只有一个应用的项目,这样做是没有问题的,而面对实际开发中多个页面的需求时,就会有它局限性。
比如一个项目中分为Mobile端和PC端,如果采用单页面模式构建的话,就会有两种开发方案:

  • 单独分开,新建两个工程
    新建两个工程的话,好处显而易见的,因为Mobile端和PC端从设计到交互到开发实现都是有差别的,分开的话,代码职责更明确一些,不会出现PC端中有一些Mobile端才需要的库,工程目录简洁明了,但无形中增加了,工程维护、联合调试和部署方面的工作

  • 融合在一起,共用一个工程 相对于"新建两个工程",节省了运维方面工作,像vue、vue-router、vuex等核心库也能共用。但缺点也很明显,代码职责不够明确,PC端代码和Mobile端代码容易冗在一起

那有没有结合上面两个方案的优点,平衡下缺点的解决方案呢?答案是有的,那就是多页面应用(MPA)。
MPA 首先它是一种应用的构建模式,是单页面应用(SPA)的扩展,弥补了单页面应用构建的不足。下面就结合在SBPO Webchat项目的真实实践,分享下Vue多页面应用(MPA)开发的最佳实践。

MPA核心 - entry

"entry" 是Webpack的一个配置属性,即webpack构建的入口起点,指示webpack应该使用哪个模块来作为构建的开始。
"entry" 属性值可以为一个String类型,也可以是Array类型,还可以是Object类型。

  • 当值为String类型时,表示当前构建只有一个入口
  • 当值为Array类型时,表示当前构建有只有一个入口,会把把数组中的元素打包成一个 "bundle"
  • 当值为Object类型时,表示当前构建有多个入口,这就是MPA构建关键
// webpack.config.js

// String
module.exports = {
    entry: './path/to/my/entry/file.js',
};

// Array
module.exports = {
    entry: ['./src/file_1.js', './src/file_2.js'],
};

// Object
module.exports = {
    entry: {
        app: './src/app.js',
        adminApp: './src/adminApp.js',
    },
};

MPA核心 - html-webpack-plugin插件

配置好 "entry" 后,后面一个核心就是 "html-webpack-plugin" 插件了。"html-webpack-plugin" 插件的作用是生成html入口文件,动态引入构建好的 "bundle"。所谓多页面也就是多个html入口文件,因此需要调用多次 "html-webpack-plugin" 插件。

const HtmlWebpackPlugin = require('html-webpack-plugin'); // 通过 npm 安装
const webpack = require('webpack'); // 访问内置的插件
const path = require('path');

module.exports = {
    entry: {
        app: './src/app.js',
        adminApp: './src/adminApp.js',
    },
    output: {
        filename: 'my-first-webpack.bundle.js',
        path: path.resolve(__dirname, 'dist'),
    },
    module: {
        rules: [
            {
                test: /\.(js|jsx)$/,
                use: 'babel-loader',
            },
        ],
    },
    plugins: [
        new webpack.ProgressPlugin(),
        new HtmlWebpackPlugin({template: './src/app/index.html'}),
        new HtmlWebpackPlugin({template: './src/adminApp/index.html'}),
    ],
};

Tips

  1. 构建MPA时,我们约定 "entry" 值中的 key 的名称,作为页面入口目录,一个 key 的名称,表示一个 SPA 应用,所有与之相关的业务代码都放到这个目录里面。
    • 比如上面代码中, "entry" 值有两个 key,分别是 appappAdmin。所以我们在工程中 "pages" 文件夹中新建两个文件夹 appappAdmin,与 "entry" 的 key 相对应。
// 工程目录
|-- build/
|-- src/
|---- pages/
|------ app/index.js
|------ appAdmin/index.js
|-- babel.config.js
|-- package.json
|-- webpack.config.js
  1. 同时,html入口文件应该放在与 "entry"值的 key 相对应的文件夹中,配置 "html-webpack-plugin" 插件的 templatefilename。这样构建出来的才是多页面
// 工程目录
|-- build/
|-- src/
|---- pages/
|------ app/
|-------- index.html
|-------- index.js
|------ appAdmin/
|-------- index.html
|-------- index.js
|-- babel.config.js
|-- package.json
|-- webpack.config.js
// 配置html-webpack-plugin插件
module.exports = {
    //...
    plugins: [
        new webpack.ProgressPlugin(),
        new HtmlWebpackPlugin({
            template: './src/app/index.html',
            filename: './src/app/index.html'
        }),
        new HtmlWebpackPlugin({
            template: './src/adminApp/index.html',
            filename: './src/adminApp/index.html'
        }),
    ],
};
// 构建后生成的文件
|-- dist/
|---- app/index.html
|---- appAdmin/index.html
|---- statics/
  1. 按照上述操作完以后,打开 app/index.html 源码,你会发现里面引入了 appAdmin 构建的内容,这样是不对的,应该是分开来引用的。app/index.html 只引用与 app 相关资源,同样 appAdmin 也是这样的。这里我们就需要设置 "html-webpack-plugin" 插件的 chunks 属性来达到我们的目的。
  • chunks 属性作用指定页面插入哪些 chunk,默认值为 all,即会把 entry 中所有构建好的 chunk 插入到页面中,因此在MPA构建中,我们就需要为每个html文件指定 chunks 属性了。注意,chunks 属性的值与 entrykey的名称也是一一对应。
// 配置html-webpack-plugin插件 chunks属性
module.exports = {
    //...
    plugins: [
        new webpack.ProgressPlugin(),
        new HtmlWebpackPlugin({
            template: './src/app/index.html',
            filename: './src/app/index.html',
            chunks: ['app']
        }),
        new HtmlWebpackPlugin({
            template: './src/adminApp/index.html',
            filename: './src/adminApp/index.html',
            chunks: ['adminApp']
        }),
    ],
};

multientry.js

如果项目中页面少的话,可以按照上面步骤手动配置。但是页面多的话,还是手动的话就不容易维护和修改了。因此我们需要创建一个 multientry.js,来帮我们做这些事情。
multientry.js 主要是根据我们约定好的多页面工程目录来动态的生成相应的 entryhtml,具体代码如下:

// multientry.js
const fs = require('fs')
const path = require('path');
const glob = require("glob");
const HtmlWebpackPlugin = require('html-webpack-plugin');

const defaultEntrys = ['index', 'main', 'app'] // 默认entry名称

module.exports = (dir) => {
    const files = glob.sync(`${dir}/*/*.js`);
    const entryInfos = files.map(f => {
        let name = path.basename(f, '.js')
        let defaultEntry = false
        if (defaultEntrys.indexOf(name) > -1) {
            const pathSnippets = path.dirname(f).split('/')
            name = pathSnippets[pathSnippets.length - 1]
            defaultEntry = true
        }
        return {
            filename: f,
            name,
            defaultEntry
        }
    })

    const entrys = {}, pages = [], contextPath = path.dirname(dir)
    entryInfos.forEach((en) => {
        entrys[en.name] = [en.filename];
        let htmlPath = `${path.dirname(en.filename)}/index.html`
        if (!fs.statSync(htmlPath)) {
            htmlPath = `${path.dirname(en.filename)}/${en.name}.html`
        }

        pages.push(new HtmlWebpackPlugin({
            template: htmlPath,
            filename: `./${en.name}/index.html`,
            inject: true,
            // favicon: `${contextPath}/favicon.ico`,
            //压缩配置
            minify: {
                removeComments: true,//删除Html注释
                collapseWhitespace: true, //去除空格
                removeAttributeQuotes: true //去除属性引号
            },
            chunksSortMode: 'auto',
            chunks: [en.name],
            multihtmlCache: true
        }));
    });

    return {
        entrys,
        pages
    }
}

然后在 "webpack.config.js" 中调用

const webpack = require('webpack'); // 访问内置的插件
const path = require('path');
const multientry = require('./multientry'); // multientry.js

module.exports = {
    entry: multientry.entrys,
    // ...
    plugins: [new webpack.ProgressPlugin()].concat(multientry.pages),
};

结束

至此结束,后面有新的Tips继续更新 ღ( ´・ᴗ・` )比心

标签:index,MPA,app,js,最佳,webpack,html,src,页面
From: https://www.cnblogs.com/Khadron/p/17650730.html

相关文章

  • vue 页面滚动时自动切换Tab标签,点击标签自动滚动页面
    功能:手机端实现切换头部tab定位到下文内容,滚动页面内容时自动定位到相对应tab逻辑:监听+tab切换完整代码:以下是完整代码:<template><divclass="box"><divclass="tab"ref="tab"><divv-for="(item,index)intabs":key=&......
  • docker上建一个jenkins容器 连gitee上代码 当更改代码后,浏览器页面更新
    1.dockerpulljenkinszh/jenkins-zh  2.设置端口  3访问本机的浏览器 跳转 4在cmd窗口输入命令 找到密码,输入,点击继续按钮 5下载默认推荐的插件 6填写账号和密码必须写自己设置的容器的账号和密码 7.  8进入主页面 9插件管理点击......
  • 什么是 Spartacus Storefront B2B store 的 My Company 菜单
    Spartacus是一个基于Angular的开源JavaScriptweb应用,与SAPCommerceCloud的RESTAPI进行交互。它的目标是提供一个稳定、可靠、可扩展的前端解决方案,让开发者能够创建全功能的商店,同时避免了与后端系统的紧密耦合。其中,B2Bstore是一个专门为B2B交易设计的商店,而My......
  • 什么是 HTML 编程里页面元素的 margin 属性
    在前端开发中,margin是一种重要的CSS属性,用于控制元素之间的空间和距离。它不仅影响元素的外观,还可以影响整个页面的布局。本文将详细解释margin的概念、用途以及通过示例演示如何在HTML中使用margin来控制元素之间的间距。概念margin是CSS(层叠样式表)中的一个属性,用于控制元素的......
  • 10. 销售型企业 Merchandising Company
    销售型企业的运营周期销售型记账方式1.永续盘存制PerpetualInventorySystem记录每笔交易对库存的影响。适用于单品价值高,交易频次低的企业。日期账户金额账户金额说明08-01库存1000应付账款1000向阿福赊购5元×200个08-10应付账款1000现金1000......
  • 使用 Python ssh 远程登陆服务器的最佳方案
    在使用Python写一些脚本的时候,在某些情况下,我们需要频繁登陆远程服务去执行一次命令,并返回一些结果。在shell环境中,我们是这样子做的。sshpass-p${passwd}ssh-p${port}-l${user}-oStrictHostKeyChecking=noxx.xx.xx.xx"ls-l"然后你会发现,你的输出有很多你并不......
  • EAS_客户端关闭编辑页面,序时簿列表页面没刷新
    可以在关闭时调用如下代码publicvoidactionSave_actionPerformed(ActionEvente)throwsException{booleanflag=auditBill_save();if(flag){//已审核的单子修改保存后直接关闭窗口ObjectuiObject=this.getUIContext().get(UIContext......
  • ios开发之--pop到指定页面
    1推出到根视图控制器[self.navigationControllerpopToRootViewControllerAnimated:YES];2推出到指定的视图控制器 for(UIViewController*controllerinself.navigationController.viewControllers){if([controllerisKindOfClass:[AViewControllerclass]]){......
  • swift--设置app图标和启动页面
    1,如下图:选择上图步骤1,然后选择步骤2,aapp图标,尺寸上面都有,b启动图,我这是创建好的,如果没有创建,先创建c这块需要置为空接着步骤b进入下图  选择1,点击2选择上图,可以看到3已经创建成功备注1:如下图按照步骤,找到a,然后取消选中fdsfgasfa备注2:选择启动图片资源,如下图按照上......
  • ios开发之--首页 导航栏隐藏 下一级页面显示,pop回来显示白条
    解决方法,在首页中实现如下两个方法,代码如下:-(void)viewWillDisappear:(BOOL)animated{[superviewWillDisappear:animated];[self.navigationControllersetNavigationBarHidden:NOanimated:NO];}-(void)viewWillAppear:(BOOL)animated{[superviewWillAppear......