Webpack生成企业站静态页面 - ajax请求

         一些项目因需求不同,如需SEO或小项目,使用angular、react或vue就大材小用了。可以通过webpack、gulp这些构建工具,也能快速完成html页面开发,并且也能使用less/sass/styus等样式预编译功能,以及将js、html分模块、分组件进行开发。

        webpack生成企业站静态页面已经讲了三篇,本该结篇,但这几天又想到以前项目上使用过MVP模式开发,一部分通过后台渲染,一部分前端渲染;这样能减轻后端压力,也能提升开发速度,让前端在写静态页面时候就能完成页面数据渲染工作。有需求就有革新的动力,所以这篇将对之前功能再度升级改造。

        当然,这种方法把数据获取到客户端通过art-template模板引擎对数据进行渲染,实现是没问题;但是完全前端进行渲染,这样对SEO优化不太友好,若是不考虑此问题不大;若将head标签和导航等公共部分在服务端渲染,其他内容通过ajax请求在客户端渲染,也能满足SEO优化需求和减轻后端压力。

        另外art-template存在在webpack编译环境 和 浏览器的生产环境,两个环境语法标签会存在冲突,在webpack构建生成静态页面时候语法标签就会被解析掉,所以要重点注意一点,虽然这是可以通过art-templte配置来解决。

1.项目环境搭建 地址:Webpack生成企业站静态页面 - 项目搭建-CSDN博客

2. 组件化 地址:Webpack生成企业站静态页面 - 组件化-CSDN博客

3. 增加数据处理能力 地址:Webpack生成企业站静态页面 - 增强数据处理能力-CSDN博客

        该篇是和前三篇连贯讲解的,所以从后面开始看的,可能地方不太清楚或运行后报错等,出现这些问题可以翻看下前几篇,这里就不再从零开始讲解项目如何搭建和完善的了。

一、配置修改

        首先修改一下webpack.config.js,对外增加暴露art-template插件,在客户端浏览器中运行时,也能使用art-template。

1.1 暴露art-template

        这里大家注意的时,添加的是template-web.js,直接用require引用art-template会报错。

        入口entry位置添加artTemplate,生成artTemplate.js到dist/js目录中。如下图:

        在module的rules中,之前对外暴露jquery位置后面,再增加一个暴露art-template的loader。如下图:

        webapck.config.js代码如下:

const { resolve } = require('path');
const webpack = require('webpack');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const artTemplate = require('art-template');
const { entrys, staticHtmls, watchHtmls } = require('./static.config');
const htmlData = require('./html.data.json');// 指定art-template模板路径
artTemplate.defaults.root = resolve(__dirname, './src');
// 指定模板名称
artTemplate.defaults.extname = '.html';module.exports = {entry: {artTemplate: ['art-template/lib/template-web.js'],jquery: ['jquery'],...entrys()},output: {filename: 'js/[name].bundle.js',      // 对入口名称进行命名,clean: true                           // 在生成文件之前清空 output 目录},module: {rules: [// MiniCssExtractPlugin.loader 提取CSS为独立文件// css-loader 会对 @import 和 url() 进行处理,就像 js 解析 import/require() 一样。{test: /\.css$/i,use: [MiniCssExtractPlugin.loader, 'css-loader']},// webpack 将 Less 编译为 CSS 的 loader。{test: /\.less$/i,use: [MiniCssExtractPlugin.loader, 'css-loader', 'less-loader']},// 匹配图片资源,指定构建后存储位置和命名{test: /\.(png|jpg|jpeg|svg|gif)$/i,type: 'asset/resource',generator: {filename: 'images/[name][ext]'}}, // 匹配html页面,并提取内部资源文件{test: /\.html$/i,loader: "html-loader",exclude: /node_modules/,options: {minimize: false,        // 不压缩html内容preprocessor: (content, loaderContext) => {// 正则达式let regEx = /<datalist>\s*{\s*[\s\S]*?\s*}\s*<\/datalist>/gi,// 区域html页面中json数据htmlResult = content.match(regEx),// 公共部分json数据returnData = {...htmlData},// 临时存储html中读取到的json数据data = {};// 判断htmlResult如果不为空,并且数组(match匹配到数据返回为数组格式)则转换字符串内容为json数据if(null!=htmlResult&&Array.isArray(htmlResult)){try {// 去除datalist标签htmlResult = htmlResult.map(item => {item = item.replace('<datalist>', '');item = item.replace('</datalist>', '');return JSON.parse(item);});// 合并数据htmlResult.forEach(item => {Object.assign(data, item);});// 合并到htmlData数据集中Object.assign(returnData, data);} catch (error) {console.error('html result:', error);}// 清除页面中数据content = content.replace(regEx, '');}return artTemplate.compile(content)(returnData);}}},// 将jquery暴露给全局对象(self、window 和 global){test: require.resolve('jquery'),loader: "expose-loader",options: {exposes: ["$", "jQuery"]}},// 对外暴露art-template{test: require.resolve('art-template/lib/template-web.js'),loader: "expose-loader",options: {exposes: ["artTemplate"]}}]},plugins: [...staticHtmls(),// 提取css文件new MiniCssExtractPlugin({filename: 'css/[name]_bundle.css',      //输出文件}),],resolve: {alias: {// 样式路径目录别名$css: resolve(__dirname, 'src/css')}},mode: 'production',devServer: {static: {// 指定服务运行目录directory: resolve(__dirname, 'dist')},watchFiles: [...watchHtmls()],compress: true,     //gzip压缩port: 3000,         //指定端口号open: true,         //服务启动后自动在浏览器打开hot: true           //开启热更}
}

1.2 html引入art-template

        要想在客户端浏览器中能调用art-template,还需要做最后一步,前篇中为了方便后期维护,将页面配置信息单独放在static.config.js文件中,需要在这把artTemplate放到chunks中,如下图:

        这样再执行webpack命令,artTemplate.bundle.js文件就成自动注入到所有html文件中。

        static.config.js文件代码如下:

const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');// 引用JS文件
const scripts = ["common", "index", "list", "article", "contact", "message"];
// 需要生成的静态页面
const htmls = [{name: "index.html", chunks: ['index']},{name: "list.html", chunks: ['list']},{name: "article.html", chunks: ['article']},{name: "contact.html", chunks: ['contact']},{name: "message.html", chunks: ['message']}
];
/*** 静态页面配置*/
module.exports = {// 重组js入口文件entrys: () => {let params = {};scripts.forEach(name => {params[name] = resolve(__dirname, `./src/js/${name}.js`);})return params;},// 重组静态页面文件staticHtmls: () =>  htmls.map(item => {return new HtmlWebpackPlugin({inject: 'body',template: resolve(__dirname, `./src/${item.name}`),filename: item.name,chunks: ['jquery', 'artTemplate', 'common', ...item.chunks],minify: false});}),// 监听热更html页面watchHtmls: () =>  htmls.map(item => resolve(__dirname, `./src/${item.name}`))
}

二、创建mock数据

        第二步,使用mock来模拟后台接口,这里使用梦学谷的mock,地址:Easy Mock。这个平台使用太简单了,就不教大家怎么使用了。现在通过这个模拟我们需要的接口,如下图:

/inviteList 接口返回数据代码如下:

{"code": 200,"data": [{"title": "2015-03-17诚招","datetime": "2014-10-2","url": "javascript:;"},{"title": "2014-03-12招聘","datetime": "2014-03-12","url": "javascript:;"},{"title": "2013-03-30诚招学生暑期工","datetime": "2014-10-2","url": "javascript:;"}],"message": "sccuess"
}

/bottomList 接口返回数据代码如下:

{"code": 200,"data": [{"title": "新春有礼——望玉岛别墅标间推出亲民价,餐饮","datetime": "2014-10-2","url": "javascript:;"},{"title": "新春有礼——望玉岛别墅标间推出亲民价,餐饮","datetime": "2014-10-2","url": "javascript:;"},{"title": "新春有礼——望玉岛别墅标间推出亲民价,餐饮","datetime": "2014-10-2","url": "javascript:;"},{"title": "新春有礼——望玉岛别墅标间推出亲民价,餐饮","datetime": "2014-10-2","url": "javascript:;"}],"message": "success"
}

/firstList 接口返回数据代码如下:

{"code": 200,"data": [{"title": "望玉岛标题","description": " 望玉岛度假村一日游活动方案:活动主题,放飞心情,走进自然,活动地;望玉岛度假村,行程特点;领略望玉岛... ","thumb": "images/index_09.jpg","url": "javascript:;"},{"title": "望玉岛标题","description": " 望玉岛度假村一日游活动方案:活动主题,放飞心情,走进自然,活动地;望玉岛度假村,行程特点;领略望玉岛... ","thumb": "images/index_10.jpg","url": "javascript:;"},{"title": "望玉岛标题","description": " 望玉岛度假村一日游活动方案:活动主题,放飞心情,走进自然,活动地;望玉岛度假村,行程特点;领略望玉岛... ","thumb": "images/index_11.jpg","url": "javascript:;"}],"message": "success"
}

        由于这里是项目演示而模拟的数据,所以好个区域是使用同一份接口数据,就不一一造模拟数据了。

三、ajax封装

        这里主要是演示如果通过ajax请求获取数据,再将数据渲染到页面,所以就简单封装并模拟。如果有朋友希望使用axios或其他相关请求工具,可以自行研究。

        由于ajax请求所有页面都需要使用到,所以这里将封装内容放到之前创建的common.js文件中,代码如下:

import '$css/common.less';(function(){// ajax请求地址const ajaxBaseUrl = "https://mock.mengxuegu.com/mock/${mock的Project ID}/webpack_ajax_pro";// 配置art-template语法模板artTemplate.defaults.rules[1].test = /{%([@#]?)[ \t]*(\/?)([\w\W]*?)[ \t]*%}/;/*** ajax 请求* @param {*} url * @param {*} params * @param {*} type */function ajaxRequest(url, params, type){return new Promise(function(resolve, reject){$.ajax({url: ajaxBaseUrl + url,type: type,data: params,success: function(res){resolve(res);},error: function(e){reject(e);}});});}/*** 封装Get请求* @param {*} id * @param {*} url * @param {*} params */$.fn.requestGetRender = function(id, url, params){let that = this;ajaxRequest(url, params, 'get').then(function(res){let html = artTemplate(id, res);$(that).html(html);}).catch(function(msg){console.error(msg);});}/*** 封装POST请求* @param {*} id * @param {*} url * @param {*} params */$.fn.requestPostRender = function(id, url, params){let that = this;ajaxRequest(url, params, 'post').then(function(res){let html = artTemplate(id, res);$(that).html(html);}).catch(function(msg){console.error(msg);});}
})();

        代码里需要注意的是art-template引擎的语法规则修改,因为<% %>和{{  }}在webpack中默认使用,如果客户端代码中不修改语法规则,webpack构建时含有<% 和 {{  的语法内容都会被匹配到和清空,这样到客户端时就获取不到任何模板内容了。

        客户端修改为开始标签为{% 和结束标签为%},代码如下:

// 配置art-template语法模板
artTemplate.defaults.rules[1].test = /{%([@#]?)[ \t]*(\/?)([\w\W]*?)[ \t]*%}/;

        另外ajax这里就不细讲了,如不了解它的,可以去看下相关文档。

        art-template在expose-loader中对外暴露名称已修改为artTemplate,所以在成功获取到数据后,可以直接使用artTemplate来渲染数据。通过artTemplate渲染后得到新的html内容,直接通过jquery将其追加到DOM中。

        另外有些人可能不清楚$.fn是什么,不了解jquery朋友可以查看下相关手册,了解其用法和作用。

四、语法标签修改

        以上工作做完后,我们可以修改index.html中数据了。将之前不管使用{{set inviteList = ... }},还是<datalist>标签引用的JSON数据,把需要通过接口获取的数据可以全部删除掉。第二步将客户端浏览器要使用到的模板信息,独立出来在template中创建indexTpl.html,单独存放。如下图:

        indexTpl.html模板代码如下:

<script type="text/html" id="tpl_top">
{%each data as item%}
<dl class="b_list"><dt><a href="#" target="_blank"><img src="{%item.thumb%}" alt="09" /></a></dt><dd><h2><a href="{%item.url%}" target="_blank">{%item.title%}</a></h2><span>{%item.description%}<a href="{%item.url%}" target="_blank">[详细情况]</a></span></dd>
</dl>
{%/each%}
</script><script type="text/html" id="tpl_bottom">
{%each data as item %}
<li><span>{% item.datetime %}</span><a href="{% item.url %}" target="_blank">{% item.title %}</a>
</li>
{%/each%}
</script>

        对页面代码分析可知,几个区域主要分为这两种模板数据结构,所以结构一样的可以共用一个模板。另外模板里的语法开始和结束标签也修改为common.js中修改的语法规则,如果未修改客户端浏览器运行时可能渲染为空。

        现在index.html文件中代码如下:

<!-- 修改当前页面对应标题 -->
{{$data.navIndexName = "首页"}}{{extend './template/layout.html'}}<datalist>
{"title": "首页"
}    
</datalist>{{block 'content'}}
<!-- mainer_wrapper -->
<div id="mainer_wrapper"><!-- main --><div class="main-container"><div class="clear"></div><!-- 广告 START --><div class="box_gg"><a href="#" target="_blank"><img src="images/index_08.jpg" alt="banner" /></a></div><!-- 广告 END --><!-- box_content 最新活动 START --><div class="box_content wd490 fl"><div class="title"><a href="#" class="more">MORE &gt;&gt;</a>最新活动</div><div class="content"><div id="newsBox"></div><div class="clear"></div></div></div><!-- /box_content 最新活动 END --><!-- box_content 旅游项目 START --><div class="box_content wd490 fl mg_l15"><div class="title"><a href="#" class="more">MORE &gt;&gt;</a>旅游项目</div><div class="content"><div id="travelBox"></div><div class="clear"></div></div></div><!-- /box_content 旅游项目 END --><!-- box_content 旅游咨询 START --><div class="box_content fl" style="width:360px;"><div class="title"><a href="#" class="more">MORE &gt;&gt;</a>旅游咨询</div><div class="content"><ul class="box_list" id="consultBox"></ul></div></div><!-- /box_content 旅游咨询 END --><!-- box_content 贵宾服务 START --><div class="box_content fl mg_l15" style="width:360px;"><div class="title"><a href="#" class="more">MORE &gt;&gt;</a>贵宾服务</div><div class="content"><ul class="box_list" id="serviceBox"></ul></div></div><!-- /box_content 贵宾服务 END --><!-- box_content 招聘信息 START --><div class="box_content fl mg_l15" style="width:240px;"><div class="title"><a href="#" class="more">MORE &gt;&gt;</a>招聘信息</div><div class="content"><ul class="box_list" id="invitBox"></ul></div></div><!-- /box_content 招聘信息 END --><div class="clear"></div></div><!-- /main -->
</div>
<!-- /mainer_wrapper -->{{include './template/indexTpl.html'}}
{{/block}}

        这里将独立出去的art-template渲染需要的模板文件,再通过include引入进来。其他不需要的数据也清理干净,页面显示更为整洁了。

        此时执行npx webpack serve命令,发现页面数据为空,这是因为还未写调用接口数据的代码,如下图:

        html代码除了将多余json数据、模板代码作了处理,还需要添加相关ID,这在后面客户端渲染页面数据会有用的。如下图:

五、页面渲染

        由于是首页数据渲染,之前也创建了index.html的入口文件,所以调用接口的功能就写在index.js文件中,代码如下:

import '$css/index.less';$(function(){// 最新活动$('#newsBox').requestGetRender('tpl_top', '/firstList', {});// 旅游项目$('#travelBox').requestGetRender('tpl_top', '/firstList', {});// 旅游咨询$('#consultBox').requestGetRender('tpl_bottom', '/bottomList', {});// 贵宾服务$('#serviceBox').requestGetRender('tpl_bottom', '/bottomList', {});// 招聘信息$('#invitBox').requestGetRender('tpl_bottom', '/inviteList', {});
});

        如果devServer打开了hot功能,在index.js中添加上面代码后,页面数据已显示出来了。如下图:

        这里写的比较简单,也是按个人思路整理的,希望对大家有帮助。不管用什么方法,只要能满足项目需求,达到预期效果,用什么方式实现并不重要。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/779876.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

RabbitMQ高级笔记

视频链接&#xff1a;【黑马程序员RabbitMQ入门到实战教程】 文章目录 1.发送者的可靠性1.1.生产者重试机制1.2.生产者确认机制1.3.实现生产者确认1.3.1.开启生产者确认1.3.2.定义ReturnCallback1.3.3.定义ConfirmCallback 2.MQ的可靠性2.1.数据持久化2.1.1.交换机持久化2.1.2.…

小米汽车SU7发布,售价21.59万起,订单总额破1亿

文 | 大力财经 小米召开新车发布会&#xff0c;正式发布小米 SU7。该车定位中大型纯电轿车&#xff0c;有 SU7、SU7 Pro、SU7 Max 三个版本&#xff0c;车身尺寸 4997/1963/1455mm&#xff0c;轴距 3000mm。售价 21.59-29.99 万。 新车发布后&#xff0c;市场反应热烈&#x…

Topaz Gigapixel AI for Mac 图像放大软件

Topaz Gigapixel AI for Mac是一款专为Mac用户设计的智能图像放大软件。它采用了人工智能技术&#xff0c;特别是深度学习算法&#xff0c;以提高图像的分辨率和质量&#xff0c;使得图像在放大后仍能保持清晰的细节。这款软件的特点在于其能够将低分辨率的图片放大至高分辨率&…

openPLC_Editor C语言编程 在mp157 arm板上调用io等使用记录

1.编程界面比较简单&#xff0c;具备PLC开发编程的四种编程方式。梯形图语言LD &#xff0c;指令表语言IL&#xff0c;结构化文本语言ST&#xff0c;功能模块图语言FBD。 2.官方使用手册。学习资料实在是太少&#xff0c;目前都是自己比较费劲的研究。 3.2 Creating Your First…

QT6实现音频输出方法

一.QT6音频调用及与QT5的区别 1.音频输入 QAudioSource代替QAudioInput类 QAudioSource类提供了一个接口&#xff0c;用于从音频输入设备接收音频数据。 Header: #include <QAudioSource> qmake: QT multimedia 2.音频输出 QAudioSink代替QAudioOutput类 QAudioSi…

【数据挖掘】实验5:数据预处理(2)

验5&#xff1a;数据预处理&#xff08;2&#xff09; 一&#xff1a;实验目的与要求 1&#xff1a;熟悉和掌握数据预处理&#xff0c;学习数据清洗、数据集成、数据变换、数据规约、R语言中主要数据预处理函数。 二&#xff1a;实验知识点总结 1&#xff1a;数据集成是将多个…

Topaz Video AI for mac 视频增强软件

Topaz Video AI for Mac是一款专为Mac用户设计的视频增强软件&#xff0c;它利用先进的人工智能技术和机器学习算法&#xff0c;为用户提供卓越的视频编辑和增强体验。 软件下载&#xff1a;Topaz Video AI for mac v4.2.2激活版 这款软件能够快速提高视频的清晰度、色彩饱和度…

激发数据潜力:企业数据中台的策略性构建与优化_光点科技

在信息时代&#xff0c;数据是企业价值链中不可或缺的一环。构建一个策略性的企业数据中台不仅能够整合分散的数据资源&#xff0c;还能提高决策效率和业务敏捷性。本文聚焦于如何策略性地构建和优化数据中台&#xff0c;以便企业能够最大化地利用数据资源&#xff0c;推动企业…

独立游戏《星尘异变》UE5 C++程序开发日志3——UEC++特供的数据类型

本篇日志将介绍FString&#xff0c;FText、FName的用法和相互转换&#xff0c;以及容器TMap&#xff0c;TArray的增删查改 一、字符串相关数据类型&#xff1a;FString、FText、FName FString是最接近std::string的类型&#xff0c;字符串本身可以看做一个存储char型的动态数…

【Django学习笔记(二)】CSS语言介绍

CSS语言介绍 前言正文1、CSS 快速了解2、CSS 应用方式2.1 在标签上应用2.2 在head标签中写style标签2.3 写到文件中 3、问题探讨&#xff1a;用Flask框架开发不方便4、选择器4.1 ID选择器4.2 类选择器4.3 标签选择器4.4 属性选择器4.5 后代选择器4.6 注意事项 5、样式5.1 高度和…

【RISC-V】如何使用release的risc-v gnu toolchain

riscv64-elf-ubuntu-22.04-gcc-nightly-2024.03.01-nightly.tar.gz 首先去release页面中获取相应的压缩包 将压缩包解压到想解压的位置&#xff0c;这里我选择了 mv Downloads/riscv64-elf-ubuntu-22.04-gcc-nightly-2024.03.01-nightly.tar.gz riscv64-tool-chain/然后解压…

python 字典练习

# 字典练习1 import time def main():month_income{1月: 8000, 2月: 8200, 3月: 7900, 4月: 6900, 5月: 8900, 6月: 12000, 7月: 8900, 8月: 6000,9月: 8900, 10月: 9200, 11月: 6200, 12月: 7000}year_income0for k,v in month_income.items():print(月份→,k,工资→,v)time.s…

中国香港男歌手张国荣 明星网页成品 html人物明星网页设计制作 明星前端网页开发 网页期末设计制作作业成品

中国香港男歌手张国荣 7页面 人物明星主题 带设计说明 jquery图片轮播特效 滚动文字 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns"http://ww…

【c++】类和对象(五)赋值运算符重载

&#x1f525;个人主页&#xff1a;Quitecoder &#x1f525;专栏&#xff1a;c笔记仓 朋友们大家好&#xff0c;本篇文章带大家认识赋值运算符重载&#xff0c;const成员&#xff0c;取地址及const取地址操作符重载等内容 目录 1.赋值运算符重载1.1运算符重载1.1.1特性&#…

刷题之动态规划

前言 大家好&#xff0c;我是jiantaoyab&#xff0c;开始刷动态规划的题目了&#xff0c;要特别注意初始化的时候给什么值。 动态规划5个步骤 状态表示 &#xff1a;dp数组中每一个下标对应值的含义是什么->dp[i]表示什么状态转移方程&#xff1a; dp[i] 等于什么1 和 2 是…

软考101-上午题-【信息安全】-网络安全

一、网络安全 1-1、安全协议 SSL(Secure Socket Layer&#xff0c;安全套接层)是 Netscape 于 1994年开发的传输层安全协议&#xff0c;用于实现 Web 安全通信。1996 年发布的 SSL3.0 协议草案已经成为一个事实上的Web 安全标准。 端口号是43。 SSL HTTP HTTPS TLS(Transpo…

XXE漏洞知识及ctfshow例题

XXE漏洞相关知识 XXE全称为XML Enternal Entity Injection 中文叫xml外部实体注入 什么是xml 简单了解XML&#xff1a; &#xff08;xml和html的区别可以简易的理解成&#xff1a;xml是用来储存数据和传输数据的而html是用来将数据展现出来&#xff09; XML 指可扩展标记语…

vue3封装Element导航菜单

1. 导航外层布局 AsideView.vue <template><el-menu:default-active"defaultActive"class"my-menu":collapse"isCollapse":collapse-transition"false"open"handleOpen"close"handleClose"><menu…

Mysql or与in的区别

创建一个表格 内涵一千万条数据 这张表中&#xff0c;只有id有建立索引&#xff0c;且其余都没有 测试1&#xff1a;使用or的情况下&#xff0c;根据主键进行查询 可以看到根据主键id进行or查询 花费了30-114毫秒&#xff0c;后面30多毫秒可能是因为Mysql的Buffer Pool缓冲池的…

大模型重塑电商,淘宝、百度、京东讲出新故事

配图来自Canva可画 随着AI技术日渐成熟&#xff0c;大模型在各个领域的应用也越来越深入&#xff0c;国内互联网行业也随之进入了大模型竞赛的后半场&#xff0c;开始从“百模大战”转向了实际应用。大模型从通用到细分垂直领域的跨越&#xff0c;也让更多行业迎来了新的商机。…