【转】使用Gulp构建网站小白教程

news/2024/5/16 8:58:06/文章来源:https://blog.csdn.net/weixin_34148508/article/details/91946931

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

原文:https://www.h5jun.com/post/gulp-build.html

什么是 Gulp?

Gulp 的官网title上对这个工具有一个比较准确的定义,叫做:基于流的自动化构建工具。如果你查看它的网页源代码,还会看到在<meta>标签里有一段更详细的描述:

Gulp.js 是一个自动化构建工具,开发者可以使用它在项目开发过程中自动执行常见任务。Gulp.js 是基于 Node.js 构建的,利用 Node.js 流的威力,你可以快速构建项目并减少频繁的 IO 操作。Gulp.js 源文件和你用来定义任务的 Gulp 文件都是通过 JavaScript(或者 CoffeeScript )源码来实现的。

所以,Gulp 是在项目开发过程中自动执行任务的一个工具,通过它可以方便地在开发时(或者发布前),对目标文件的内容进行I/O操作。

由于 Gulp 是基于流的,所以 Gulp 对于文件内容的操作就像是水槽对于水流,水流流经水槽,水槽将水流塑造成不同的形状。

既然是基于流的,在进一步理解 Gulp 前,我们最好先来理解什么是流。

Stream 流

在计算机系统中文件的大小是变化很大的,有的文件内容非常多非常大,而 Node.js 里文件操作是异步的,如果用一个形象的比喻来形容将一个文件的内容读取出来并写入另一个文件中,可以将它想象成文件内容像是水流,从一个文件“流”入另一个文件。

stream

在node里面,读写文件可以用“流”来描述:

"use strict"let fs = require("fs")fs.createReadStream("./in.txt").pipe(fs.createWriteStream("./out.txt"))

上面的代码除了将 in.txt 文件中的内容输出到 out.txt 之外,不做其他任何事情,相当于复制了一份数据,从语法形式上可以看到,“数据流”从 fs.createReadStream 创建然后经过 pipe 流出,最后到 fs.createWriteStream。

在这输入流到输出流的中间,我们可以对“流”做一些事情:

"use strict"let fs = require("fs")
let through = require("through2")fs.createReadStream("./in.txt").pipe(through.obj(function (contents, enc, done) {if(enc === "buffer"){contents = contents.toString("utf-8")enc = "utf-8"}done(null, contents, enc)})).pipe(through.obj(function (contents, enc, done) {done(null, contents.toUpperCase(), enc)})).pipe(through.obj(function (contents, enc, done) {contents = contents.split("").reverse().join("")done(null, contents, enc)})).pipe(fs.createWriteStream("./out.txt"))

在上面的代码里,我们通过 Node.js 的 through2 库(这是一个针对“流”的包装库),将输入流一步步转换成输出流,在中间的 pipes 中我们先是将 Buffer 转成 String,然后将它变成大写,最后再 reverse 然后传给输出流。

所以如果 in.txt 的文件内容是 hello world~,那么 out.txt 的文件内容将是: ~DLROW OLLEH

基于流的 Gulp

月影觉得 Gulp 的文档其实写得挺烂的,点中文文档页面除了让你看入门指南、API文档、CLI文档、编写插件文档之外就没什么了,但实际上真要用 Gulp 的高级功能,这些文档简直就和教人如何画马一样:

画马

既然 Gulp 是基于流的,我们就要理解 Gulp 如何控制和操作流。

然而在这之前,我们还要先看最基础的(还没安装 Gulp 的同学可以照前面那个入门指南安装一下~)

var gulp = require("gulp")gulp.task("sync1", function() {console.log("我是一个同步任务")
})gulp.task("async", function(done) {setTimeout(function(){console.log("我是一个异步任务")done()}, 2000)  
})

我们可以看到 Gulp 是基于任务的,gulp.task 可以定义一个任务,这样的话,我们在命令行下就可以通过 gulp 任务名 的方式来执行命令了:

$ gulp sync1
[18:27:12] Using gulpfile ~/Workspace/yuntu/myblog-master/item/photohome/gulpfile.js
[18:27:12] Starting "sync1"...
我是一个同步任务
[18:27:12] Finished "sync1" after 122 μs$ gulp async
[18:27:48] Using gulpfile ~/Workspace/yuntu/myblog-master/item/photohome/gulpfile.js
[18:27:48] Starting "async"...
我是一个异步任务
[18:27:50] Finished "async" after 2 s

Gulp 的任务可以是同步和异步,在异步任务中确定任务完成,可以通过调用函数参数 done 来实现。

Gulp 也允许我们将任务组合起来执行:

var gulp = require("gulp")
var through = require("through2")gulp.task("sync1", function() {console.log("我是一个同步任务")
})gulp.task("sync2", function() {console.log("我是另一个同步任务")
})gulp.task("sync3", function() {console.log("我是又一个同步任务")
})gulp.task("async", function(done) {console.log("老大喊我去搬砖")setTimeout(function(){console.log("我是一个异步任务")done()}, 2000)
})gulp.task("syncs", ["async", "sync1", "sync2", "sync3"], function(){console.log("砖搬完了!")})
$ gulp syncs
[18:30:30] Using gulpfile ~/Workspace/yuntu/myblog-master/item/photohome/gulpfile.js
[18:30:30] Starting "async"...
老大喊我去搬砖
[18:30:30] Starting "sync1"...
我是一个同步任务
[18:30:30] Finished "sync1" after 142 μs
[18:30:30] Starting "sync2"...
我是另一个同步任务
[18:30:30] Finished "sync2" after 55 μs
[18:30:30] Starting "sync3"...
我是又一个同步任务
[18:30:30] Finished "sync3" after 43 μs
我是一个异步任务
[18:30:32] Finished "async" after 2 s
[18:30:32] Starting "syncs"...
砖搬完了!
[18:30:32] Finished "syncs" after 38 μs

我们看到说 gulp.task 可以有依赖,只要第二个参数传一个数组,中间加上依赖的任务就行了,而数组里面的这些任务是并行处理的,不会一个执行完才执行另一个(同步任务的输出比异步任务的结束早)。

以上是 Gulp 基本的任务模型。对于每个 task,Gulp 通常用来操作文件输入和输出流,因此 Gulp 封装了批量操作文件流的 api:

gulp.task("src-dist", function(){gulp.src("./*.html").pipe(gulp.dest("./dist"))
})

上面的命令表示将当前目录下所有的 .html 文件匹配出来,依次输出到目标文件夹 ./dist 中去。

我们还可以用更高级的通配符:

gulp.task("src-dist", function(){gulp.src("./**/*.html").pipe(gulp.dest("./dist"))
})

这样处理的 html 文件不仅仅匹配当前目录下的,还包括所有子目录里。关于输入这块,具体的用法还有很多,遵循的规范是glob模式,可以参考node-glob

处理文件的内容

与上面说的 FileSystem 文件流类似,如果我们不做什么别的事情,那么我们就只是将文件从源 src,拷贝到了目的地 dest,其他的啥也没做,那么显然,我们可以做那么一些事情,在这里,我们尝试处理一下 index.html:

gulp.task("build-index", function(){gulp.src("./index.html").pipe(through.obj(function(file, encode, cb) {var contents = file.contents.toString(encode)var HTMLMinifier = require("html-minifier").minifyvar minified = HTMLMinifier(contents, {minifyCSS: true,minifyJS: true,collapseWhitespace: true,removeAttributeQuotes: true})file.contents = new Buffer(minified, encode)cb(null, file, encode)})).pipe(gulp.dest("./dist"))
});

gulp.src 的输入流和 fileReadStream 会有一点点不一样,它的第一个参数不是一个 Buffer,而是一个包含文件信息和文件内容的对象,第二个参数是文件的编码,因此我们可以通过

var contents = file.contents.toString(encode)

将文件内容转成字符串。之后,我们使用 html-minifier 对文件的HTML内容和内联的样式、脚本进行压缩,这样就简单完成了首页 index.html 的优化!

进一步优化

前面只完成了优化的第一步,我们还没考虑外链资源该怎么处理呢,外链资源包括 js、 css 和图片。在处理之前,我们来约定一些规范:

  • 页面 js 存放在 ./static/js 下,公共的库放在 ./static/js/lib 下,公共库只压缩不合并,页面 js 压缩并合并。

  • 页面 css 存放在 ./static/css 下,公共的css放在 ./static/css/common 下,公共 css 只压缩不合并,页面 css 压缩并合并。

  • 图片资源中小于3kb的图片以 base64 方式内联,图片放在 ./static/img 下。

压缩 js

function minifyAndComboJS(name, encode, files){var fs = require("fs")var UglifyJS = require("uglify-js")var content = ""files.forEach(function(js){var minified = UglifyJS.minify(js).codecontent += minified})if(content){var combo = "static/js/" + name}fs.writeFileSync(combo, content)gulp.src(combo).pipe(gulp.dest("./dist/static/js"))
}

压缩 js lib

gulp.task("build-js-lib", function(){gulp.src("./static/js/lib/**/*.js").pipe(through.obj(function(file, encode, cb) {var UglifyJS = require("uglify-js")var contents = file.contents.toString(encode)var minified = UglifyJS.minify(contents, {fromString:true}).codefile.contents = new Buffer(minified, encode)cb(null, file, encode)})).pipe(gulp.dest("./dist/static/js/lib"))
})

压缩 css

function minifyAndComboCSS(name, encode, files){var fs = require("fs")var CleanCSS = require("clean-css")var content = ""files.forEach(function(css){var contents = fs.readFileSync(css, encode)var minified = new CleanCSS().minify(contents).stylescontent += minified})if(content){var combo = "static/css/" + name}fs.writeFileSync(combo, content)gulp.src(combo).pipe(gulp.dest("./dist/static/css"))
}

压缩公共 css

gulp.task("build-common-css", function(){gulp.src("./static/css/common/**/*.css").pipe(through.obj(function(file, encode, cb) {var CleanCSS = require("clean-css")var contents = file.contents.toString(encode)var minified = new CleanCSS().minify(contents).stylesfile.contents = new Buffer(minified, encode)cb(null, file, encode)})).pipe(gulp.dest("./dist/static/css/common"))
})

处理图片

//内联小图片
var imgs = $("img")
for(var i = 0; i < imgs.length; i++){var img = $(imgs[i])var src = img.attr("src")if(/^static\/img/.test(src)){var stat = fs.statSync(src)var ext = require("path").parse(src).extif(stat.size <= 3000){var head = ext === ".png" ? "data:image/png;base64," : "data:image/jpeg;base64,"var datauri = fs.readFileSync(src).toString("base64")img.attr("src", head + datauri)}}
}

压缩 HTML

contents = $.html()//压缩 HTML
var HTMLMinifier = require("html-minifier").minifyvar minified = HTMLMinifier(contents, {minifyCSS: true,minifyJS: true,collapseWhitespace: true,removeAttributeQuotes: true
})

然后,在处理 index.html 的时候,我们可以使用 cheerio 来解析文件,将要处理的外链从文档中提取出来。

提取 js 和 css 外链处理

var $ = require("cheerio").load(contents, {decodeEntities: false})//处理外链 css
var links = $("link")
var cssToCombo = []for(var i = 0; i < links.length; i++){var link = $(links[i])if(link.attr("rel") === "stylesheet"){var href = link.attr("href")if(/^static\/css\/(?!common)/.test(href)){cssToCombo.push(href)if(cssToCombo.length == 1){link.attr("href", "static/css/index.min.css")}else{link.remove()}}}
}
minifyAndComboCSS("index.min.css", encode, cssToCombo)//处理外链 js
var scripts = $("script")
var jsToCombo = []
for(var i = 0; i < scripts.length; i++){var s = $(scripts[i])//判断script标签确实是jsif(s.attr("type") == null || s.attr("type") === "text/javascript"){var src = s.attr("src")if(src){//外链的js,默认只处理以/static/开头的资源if(/^static\/js\/(?!lib)/.test(src)){jsToCombo.push(src)if(jsToCombo.length == 1){s.attr("src", "static/js/index.min.js")}else{s.remove()}   }}}
}
minifyAndComboJS("index.min.js", encode, jsToCombo)

最后是完整的代码:

var gulp = require("gulp")
var through = require("through2")gulp.task("build-index", ["build-js-lib", "build-common-css"], function(){gulp.src("./index.html").pipe(through.obj(function(file, encode, cb) {var fs = require("fs")var contents = file.contents.toString(encode)var $ = require("cheerio").load(contents, {decodeEntities: false})//处理cssvar links = $("link")var cssToCombo = []for(var i = 0; i < links.length; i++){var link = $(links[i])if(link.attr("rel") === "stylesheet"){var href = link.attr("href")if(/^static\/css\/(?!common)/.test(href)){cssToCombo.push(href)if(cssToCombo.length == 1){link.attr("href", "static/css/index.min.css")}else{link.remove()}}}}// 压缩cssminifyAndComboCSS("index.min.css", encode, cssToCombo)// 处理外链jsvar scripts = $("script")var jsToCombo = []for(var i = 0; i < scripts.length; i++){var s = $(scripts[i])// 判断script标签确实是jsif(s.attr("type") == null || s.attr("type") === "text/javascript"){var src = s.attr("src")if(src){// 外链的js,默认只处理以/static/开头的资源if(/^static\/js\/(?!lib)/.test(src)){jsToCombo.push(src)if(jsToCombo.length == 1){s.attr("src", "static/js/index.min.js")}else{s.remove()}   }}}}// 压缩jsminifyAndComboJS("index.min.js", encode, jsToCombo)// 处理内联图片var imgs = $("img")for(var i = 0; i < imgs.length; i++){var img = $(imgs[i])var src = img.attr("src")if(/^static\/img/.test(src)){var stat = fs.statSync(src)var ext = require("path").parse(src).extif(stat.size <= 3000){var head = ext === ".png" ? "data:image/png;base64," : "data:image/jpeg;base64,"var datauri = fs.readFileSync(src).toString("base64")img.attr("src", head + datauri)}}}        // 压缩HTMLcontents = $.html()var HTMLMinifier = require("html-minifier").minifyvar minified = HTMLMinifier(contents, {minifyCSS: true,minifyJS: true,collapseWhitespace: true,removeAttributeQuotes: true})file.contents = new Buffer(minified, encode)cb(null, file, encode)})).pipe(gulp.dest("./dist"))
})// 压缩css
function minifyAndComboCSS(name, encode, files){var fs = require("fs")var CleanCSS = require("clean-css")var content = ""files.forEach(function(css){var contents = fs.readFileSync(css, encode)var minified = new CleanCSS().minify(contents).stylescontent += minified})if(content){var combo = "static/css/" + name}fs.writeFileSync(combo, content)gulp.src(combo).pipe(gulp.dest("./dist/static/css"))
}// 压缩css/common/
gulp.task("build-common-css", function(){gulp.src("./static/css/common/**/*.css").pipe(through.obj(function(file, encode, cb) {var CleanCSS = require("clean-css")var contents = file.contents.toString(encode)var minified = new CleanCSS().minify(contents).stylesfile.contents = new Buffer(minified, encode)cb(null, file, encode)})).pipe(gulp.dest("./dist/static/css/common"))
})// 压缩js
function minifyAndComboJS(name, encode, files){var fs = require("fs")var UglifyJS = require("uglify-js")var content = ""files.forEach(function(js){var minified = UglifyJS.minify(js).codecontent += minified})if(content){var combo = "static/js/" + name}fs.writeFileSync(combo, content)gulp.src(combo).pipe(gulp.dest("./dist/static/js"))
}// 压缩js/lib/
gulp.task("build-js-lib", function(){gulp.src("./static/js/lib/**/*.js").pipe(through.obj(function(file, encode, cb) {var UglifyJS = require("uglify-js")var contents = file.contents.toString(encode)var minified = UglifyJS.minify(contents, {fromString:true}).codefile.contents = new Buffer(minified, encode)cb(null, file, encode)})).pipe(gulp.dest("./dist/static/js/lib"))
})

总结

我们用 Gulp 创建了一个非常简单的构建脚本,它可以压缩合并我们项目的 js 和 css 并处理小图片,我们还可以给它进一步增加其他功能,例如给压缩的文件添加版本号,或者根据内容计算签名以实现更新后不被缓存,我们还可以用 CDN 服务的 sdk 将资源发布到 CDN 并替换原始链接,同时,我们可以不用每次发布所有的文件,我们可以在开发的时候用 gulp.watch 来监控文件的修改,以实现增量的编译发布。

总之,我们可以用 gulp 来做许多有用的事情,来完善我们的构建脚本,而这一切都因为 gulp 基于流的构建以及 NPM 丰富的库变得非常简单。最后的最后,由于我们从头使用 through2 来处理任务,所以我们在具体实现功能的时候还是略微繁琐,事实上 gulp 提供了不少有用的插件,这些插件直接返回 stream 对象,可以让构建过程变得更简单,具体的可以多研究官方的文档。

PS

特别需要注意的是,在此Demo或者说小项目中,最后的压缩步骤需要node包管理工具,利用npm安装相应的包,而这涉及到nodejs的基础知识,例如在构建Demo一开始,可以利用npm init来创建package.json文件,利用npm install来安装包文件等。另外,在index.html中js和css等路径需要以static/开始,而不是./staitc/开始

 

转载于:https://my.oschina.net/iNiL0119/blog/749409

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

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

相关文章

大型网站架构演变

第二遍阅读《大型网站技术架构》&#xff0c;真心觉得书中的内容很好&#xff0c;推荐大家去阅读。下面是书中对大型网站架构演变过程的介绍。 对于一个小型企业级网站,通常的架构如下图&#xff1a; 随着用户数量的增多&#xff0c;可以将应用服务与数据服务分离以提高性能&a…

mysql 数据库初始化安装_MYSQL初始化 - MYSQL数据库安装教程全攻略(图)_数据库技术_Linux公社-Linux系统门户网站...

二、MySQL初始化:MYSQL初始化主要完成管理员密码设定和测试数据库连接是否正常等操作。第一步:进入c:\usr\mysql\bin目录&#xff0c;这个是我们刚刚安装时选择的目录。(如图7)图7&#xff1a;进入c:\usr\mysql\bin目录第二步:找到该目录下的名为winmysqladmin.exe的程序&#…

华为服务器如何设置网站dns,设置为正确的DNS 服务器地址

设置为正确的DNS 服务器地址 内容精选换一换域名的DNS服务器定义了域名用于解析的权威DNS服务器。通过华为云注册成功的域名默认使用华为云DNS进行解析&#xff0c;详细内容&#xff0c;请参见华为云DNS对用户提供域名服务的DNS是什么&#xff1f;。若您选择非华为云DNS进行域名…

《流量的秘密: Google Analytics网站分析与优化技巧(第3版)》一1.2 网站分析可以提供的信息...

本节书摘来自异步社区《流量的秘密: Google Analytics网站分析与优化技巧(第3版)》一书中的第1章&#xff0c;第1.2节&#xff0c;作者【英】Brian Clifton&#xff0c;更多章节内容可以访问云栖社区“异步社区”公众号查看 1.2 网站分析可以提供的信息 流量的秘密: Google Ana…

css grid随页面大小_CSS Grid 系列(下)-使用Grid布局构建网站首页

by Chris House译者&#xff1a;若愚老师更好的阅读体验&#xff1f;可在 饥人谷技术博客 查看原文要看懂这篇文章&#xff0c;推荐先简单过一遍姊妹篇 CSS Grid 系列(上)-Grid布局完整指南当我开始一个项目&#xff0c;并开始计划如何布局主页时&#xff0c;我的大脑复现出浮动…

程序页面闪退 进程还在_企业想开发线上业务,那么该做网站、APP、小程序还是公众号?...

很多企业想开发线上业务&#xff0c;那么该做网站、APP、小程序还是公众号&#xff1f;这是很多企业都会遇到的问题。你可能会问&#xff0c;既然都有那么多的选择那么多方向&#xff0c;我们为什么不全做了&#xff1f;当然&#xff0c;如果企业财大气粗&#xff0c;效果肯定不…

seo日常工作表_SEO主要做什么工作?SEO优化入门之网站的日常维护

《种豆南山下——网站的日常维护》--作者&#xff1a;推云阿航日常维护&#xff1a;对于新站&#xff1a;1、未收录的每日提交链接&#xff0c;已经收录的每日投诉快照&#xff0c;直至更新。2、快照一旦更新&#xff0c;就需要先查一下网站site和title的排名&#xff0c;判断权…

从主机访问虚拟机中的网站系列教程(VBox篇)

最近大家开始搭上我们这个学期的关键——Siteweaver&#xff0c;为了这个东西大家无所不用其极&#xff0c;有人换系统&#xff0c;有人开始学习用虚拟机。用虚拟机的同学会发现&#xff0c;我们在使用虚拟机搭建网站的时候&#xff0c;怎么可以方便地从主机和局域网访问到虚拟…

asp的网站能封装成app吗_在线网站封装APP评测:性价比最高的竟然是它?

如果你有一个网站&#xff0c;想给网站加个壳&#xff0c;封装成一个app&#xff0c;点开之后显示的还是网站&#xff0c;可以实现吗&#xff1f;我的回答是肯定的&#xff0c;这就是网站封装APP。现在APP的开发成本很高&#xff0c;很多热倾向于通过封装打包网站来实现“快速开…

linux文件的链接可分为6,linux中有几种文件类型_网站服务器运行维护,linux,文件类型...

linux下编译程序找不到头文件_网站服务器运行维护linux下编译程序找不到头文件的解决方法是&#xff1a;1、首先执行【find / -name xxx.h】命令&#xff0c;查找路径&#xff1b;2、然后执行【gcc test.c -o test -I /usr/local/include/xxx】命令即可。1、普通文件( 数据文件…

linux nginx php网站渗透,Linux系统下nginx+php清理服务器网站日志怎么弄

Linux系统下nginxphp清理服务器网站日志怎么弄发布时间&#xff1a;2020-10-16 15:01:59来源&#xff1a;亿速云阅读&#xff1a;78作者&#xff1a;小新这篇文章主要介绍了Linux系统下nginxphp清理服务器网站日志怎么弄&#xff0c;具有一定借鉴价值&#xff0c;需要的朋友可以…

onmouseover 事件

, , , , , , , , , , , , , to , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , 支持该事件的 JavaScript 对象&#xff1a;layer, link实例 1在下面的例子中&#xff0c;我们将在用户把鼠标指针移动到图像上时显示一个对话框&#xff1a; onmouseover"…

Nginx配置HTTPS证书网站

前提&#xff1a; 1、主机需要先安装openssl 2、编译安装nginx时&#xff0c;要加上--with-http_ssl_module 这个ssl模块 现在开始配置&#xff1a;&#xff08;我当时配置时&#xff0c;主机已安装了openssl&#xff0c;但编译时没有加载http_ssl_module模块&#xff0c;所以…

nicetool好工具_上进青年研习社丨这6个工具合集网站,抵过上百个软件!

文丨小渔不知道你们有没有这样的经历&#xff1a;为了一些小的需求&#xff0c;在手机上或是电脑上下了一堆软件。虽然用过觉得也挺好用的&#xff0c;但是平时的使用频率真的不高啊。等你把它们都卸载了&#xff0c;过了一段时间突然又需要用它了。所以&#xff0c;今天小渔要…

快站模板 连接mysql_如何轻松建站?站点一键部署搭建(详细教程)

来越多的人选择个人建站&#xff0c;个人站长虽然门槛很低&#xff0c;但是有些朋友觉得Linux服务器各种复杂的命令脚本让自己没法搭建环境。今天就给大家推荐一款使用方便、功能强大的快速建站工具——云帮手&#xff0c;支持 Linux 与 Windows 系统&#xff0c;可一键配置搭建…

查看 db2 正在 运行的sql_介绍两个刷 SQL 题的网站

今天有朋友在群里问到&#xff1a;在哪可以刷 SQL 题&#xff1f;其实&#xff0c;要刷 SQL 题&#xff0c;对着《SQL COOKBOOK》、《SQL 经典实例》这两本书&#xff0c;把所有实例从头到尾全部实现一遍就很厉害了。不过&#xff0c;我想她的本意是想知道有没有关于 SQL 的 On…

html使用bootstrap无效果,[0失败]手把手教你用Bootstrap做个人网站

作为一个纯小白手残星人&#xff0c;总想自己做一个网站&#xff0c;Wix&#xff0c;Strikingly这一类的可视化建站的工具&#xff0c;自由度不高&#xff0c;付费贼贵&#xff0c;自己做的又不好看又费时间&#xff0c;听说bootstrap这种前端框架可以自己做网页&#xff0c;之…

实验六:MYSQL+PHP的网站搭建

实验目的&#xff1a;掌握MYSQLPHP的网站的搭建过程实验准备&#xff1a;一台Server&#xff0c;一台Client实验前的准备&#xff1a;搭建一台web服务器&#xff08;过程省略&#xff09;实验步骤&#xff1a;步骤一1.安装PHP数据包解压php-5.1.4-Win32这个解压包&#xff0c;把…

沙发家具网站源码_2020年(双十二)沙发选购全攻略~~

沙发算是家庭装修最昂贵的家具之一&#xff0c;当然我特别建议选购时亲自试用感受它们&#xff0c;由于这些物品尺寸的特殊性&#xff0c;网购最担心的就是购买后自己如果不喜欢&#xff0c;退货麻烦以及昂贵的运费。现在由于网上购物的便利&#xff0c;以及网上的风格多样化&a…

java项目修改html文件类型,爱了!Guide哥手把手教你搭建一个文档类型的网站!免费且高速!...

这篇文章 Guide 哥就手把手教大家搭建一个像下面这样的文档类型的网站&#xff0c;你可以用来当做项目的说明文档&#xff0c;也还可以当做自己专属的知识小仓库。一.前置条件确保自己电脑下载安装了 NPM 并且使用这个命令&#xff1a; npm i docsify-cli -g安装了 docsify-cli…