谢超的技术博客

主攻前端,略懂后端


  • 首页

  • 分类

  • 归档

nginx中对vue(spa)项目的缓存配置

发表于 2019-11-22 | 分类于 前端 | 阅读次数:

目前前端的项目基本上被vue、react、angular霸占了,构建打包也基本上都是基于webpack,3个不同框架其实都提供了一套比较完成的开发工具链,最典型的其实就是将构建完成的文件加上hash值,如a.js 在构建完成后会变成a.abad3333ss.js文件,这样在前端项目发布新版部署的时候,能让浏览器不缓存a.js文件。

关于部署,目前前端基本上都是基于nginx进行独立部署的,方便快捷没有跨域问题,使用nginx部署就会有缓存问题,也就是浏览器访问你的域名之后,默认是会把所有静态文件缓存到本地的,针对这种情况,有2中解决方案:

nginx配置文件不缓存

不缓存,也就是在nginx的配置中,强制设置所有文件均不会在浏览器缓存,这样不管项目发版之后有没有对项目的静态文件的文件名设置hash值,(版本号),浏览器始终会去服务器请求最新的文件,坏处就是加载速度会稍慢,尤其是在网络条件不理想的情况下,具体配置如下:

1
2
# 在nginx.conf文件中的location或者server中设置请求cache-control请求头
add_header Cache-Control no-cache,no-store,must-revalidate;

静态文件加hash,nginx配置不缓存html

既然各开发框架构建的前端项目都对静态文件的文件名增加hash值,那么肯定要利用起来,但是直接使用会有问题。

构建出的静态文件-index.html 未改名,其他静态文件名是改了,但是文件引用全部是在这个html文件中的,如果index.html文件也缓存了,那么他引用的对应的文件也不会发生变化!这时候需要针对html单独进行缓存设置:

1
2
3
4
5
6
# 在对应的location中增加以下代码,即html后缀的文件名不会进行缓存
location / {
if ($request_filename ~* ^.*?.(html|htm)$){
add_header Cache-Control no-cache,no-store,must-revalidate;
}
}

nginx报proxy_temp Permission denied 错误解决

发表于 2019-11-22 | 分类于 linux | 阅读次数:

在使用nginx的时候,有时会发现报 proxy_temp Permission denied 错误,这时候nginx会报error信息,原因其实就是 proxy_temp 没有读取权限,有两种解决办法:

  1. 将nginx启动用户改为有权限的用户(如 root)或者将proxy_temp授权给启动用户

    1
    user root;
  2. 更改nginx的配置,将缓冲区调整大一点,以下几项需要同时调整配置

    1
    2
    3
    4
    5
    6
    7
    http{
    #proxy缓存设置
    proxy_buffer_size 10m;
    proxy_buffers 4 10m;
    proxy_busy_buffers_size 10m;
    proxy_temp_file_write_size 10m;
    }

webpack babel根据配置打包生成对应的polyfill

发表于 2019-02-12 | 分类于 前端 | 阅读次数:

在使用webpack+babel的时候,经常会配到需要添加polyfill,根据搜索到的资料一般都是在入口文件引入polyfill,这样的话,打包出来的文件会比较大,不太适合移动端的项目,多番资料查找验证之后,可以对.babelrc文件做以下处理即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
"presets": [
[
"@babel/preset-env",
{
"modules": false, //设置ES6 模块转译的模块格式 默认是 commonjs
"targets": { // 配支持的环境
"browsers": ["ie >=10"]
},
"useBuiltIns": "usage", // 是否开启自动支持 polyfill
"debug": true // debug,编译的时候 console
}
]
],
"plugins": ["@babel/transform-runtime"]
}
// 其实就是对babel做配置,但是一般项目的starter里边很少有如此配置的,所以就给忽略了

基于ES5的prototype进行模块化开发

发表于 2019-02-12 | 分类于 前端 | 阅读次数:

目前前端的模块化开发/多人协作开发基本上分为以下几类:

  • 按功能划分不同的文件,最后进行组合
  • 按页面或者模块进行划分,多人编写不同的JS/HTML文件,最后组合
    经常为了项目进度,会出现多人开发同一个页面的情况,这样的话,经常会发生代码冲突的现象,除非提前及其规划地约定好页面内的模块,
  • 其实还有一种以prototype进行模块划分的非常好的方式,prototype内部的变量可以进行隔离,个人在prototype内部进行各自的功能开发,也不会出现代码冲突的情况,对外暴露其他模块需要的接口即可,对多人协同开发非常友好。

页面结构开发

首先编写好页面的基础html结构和基础js,主要是在js文件内进行模块隔离,参考如下代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 如index页面
// index.js
// 首先定义一个index的ES5类,并且定义好该类的初始化方法及内部定义模块并对其进行实例化
function Index(){
this.CONST()
this.INIT()
}
Index.prototype.CONST = function(){
// 在这里定义页面内部的局部变量,并且不会污染外部环境,统一使用自定义的get/set方法进行存取
var data = {
val1: '123',
val2: '234'
}
this.get = function(key){
return data[key]
}
this.set = function(key,val){
data[key] = val
}
}
Index.prototype.INIT = function(){

}
var index = new Index()

编写页面的结构模块

在完成页面类的基础结构后,根据不同页面功能编写功能模块,比如页面内的查询参数可以当作独立模块,表格也可以当作独立模块,多人开发时,个人开发独立的模块即可,模块之间通过类内部的方法(接口)进行通信

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
Index.prototype.SearchValues = function(){
var self = this
var queryParams = {}
// 对外暴露获取参数的接口/方法,但不会暴露内部变量
self.getQueryParams = function(){
return queryParams
}
}
Index.prototype.TableModule = function(){
var self = this
var test = 123
var initTable = function(){
console.log(test)
}
// 同样对外暴露 initTable 方法
self.renderTable = initTable
}
// 在定义好页面功能模块及需要初始化的方法之后,在INIT模块内进行如下处理

Index.prototype.INIT = function(){
//首先加载各功能模块
this.SearchValues()
this.TableModule()
// 模块加载完成之后再初始化功能
this.renderTable()
}

nuxt express项目中使用中间件(serverMiddleware)

发表于 2018-10-31 | 分类于 前端 | 阅读次数:

Nuxt,作为一款优秀的基于Vue的服务端渲染(SSR)框架,既可以使用他的服务器渲染模式,也可以打包成静态页面,甚至也可以将其打包未SPA(单页面应用)

使用Nuxt官方模板初始化项目的时候,可选择不同的基于Nodejs的服务端框架,我选用的是Express,其他框架也类似。

Express中有许多的官方或者第三方的中间件,其实也就是渲染页面之前需要做的操作,比如日志记录,cookie解析,url解析,权限认证等等,在Nuxt中,中间件分两种:

  • 基于Nodejs或者Express或者自行开发的服务端中间件(serverMiddleware)
  • 基于Vue路由,也就是Nuxt渲染页面之前的中间件,可以看作是Vue Router的钩子

服务端中间件的开发使用

默认在 /server/index.js文件中,启动了一个express服务,在start函数中使用了nuxt作为express的中间件,我们自行开发或者使用的中间件有两种方式:

  1. 在nuxt中间件使用之前调用

    1
    2
    3
    4
    5
    // 需要在nuxt中间件调用前使用,否则页面会在nuxt中间件中渲染出来
    app.use((req,res,next)=>{
    console.log(req.headers)
    })
    app.use(nuxt.render)
  2. 使用nuxt的serverMiddleware

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    // 1.在项目根目录下建一个serverMiddleware的文件夹,再建立 一个auth.js的文件
    //auth.js
    export default function(req,res,next){
    // console.log(req.headers)
    // res.redirect(301,'https://www.baidu.com')
    // res.status(200).send('<p>12355</p>')
    // 在该中间件中,你甚至可以做渲染拦截,直接send你自定义的数据
    next()
    }

    // 2.在nuxt的配置文件中(nuxt.config.js)调用该中间件
    module.exports = {
    serverMiddleware: [
    '@/serverMiddleware/auth'
    ],
    }
    // 或者可以给路径参数,跟express中是一样的
    module.exports = {
    serverMiddleware: [
    {path:'/api', handler:'@/serverMiddleware/auth'}
    ],
    }

基于vue的理解实现一个简单的mvvm框架

发表于 2018-09-30 | 分类于 前端 | 阅读次数:

在写了很多的vue项目之后,就比较想去了解vue的实现方式,因为现在的前端框架主要是Vue/React/Angular,除了React之外都可以实现数据的双向绑定,React也可以稍微做多一点,自己实现,关键问题在是数据与页面(模板)的绑定、同步数据更新/页面更新。
类vue的mvvm框架叫做 模板(model)-视图(view)-视图模板(viewmodel),核心就是将view耦合model,并且在model更新的时候操作view中的dom变化

mvvm框架流程解析

本文章的代码参考了DMQ/mvvm
vue采用了数据劫持的方式(observer)来进行视图-模板的绑定更新,

图片来自DMQ/mvvm
流程:

  • observer:数据监听,由observer对数据模型使用Object.defineProperty对数据的get、set方法进行劫持,设置数据时通知订阅者(watcher)更新,获取数据时绑定订阅者,
  • compile:模板/指令编译器,将html文件中的指令(v-model,@clickj,{{}})等特定规则的字符串解析成mvvm中的数据,并且将其添加为一个观察者,同时执行具体的dom更新、事件绑定等
  • watcher:订阅者,模板/数据观察者,一旦观察到了数据的变动,则进行数据更新
  • dep:消息订阅器,连接compile与watcher,在数据劫持中绑定watcher

mvvm框架页面示例

以一个简单的页面示范mvvm框架的实现
实现的效果:

html文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>webpack4 demo</title>
</head>
<body>
<div class="main" id="app">
<input type="text" v-model="str">
<div style="color:red">{{str}}</div>
<!-- <input type="text" v-model="child.childData"> -->
<div style="color: blue" v-text="child.childData"></div>
<div style="color: blue" v-text="text"></div>
<!-- {{str}} -->
<input type="button" value="清除" @click="clear">
<input type="button" value="设置子对象" @click="setChild">
</div>
</body>
</html>

js文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import Mvvm from './mvvm'

let mv = new Mvvm({
el: "#app",
data: ()=>{
return {
str : '我是测试',
someStr: '别的内容',
child: {
childData:'我是子对象',
},
text: '我是text'

}
},
methods: {
setChild(){
console.log('子对象的事件绑定')
this.child.childData = Math.round((Math.random() * 5 * 100))/100
},
clear(){
console.log('绑定事件成功')
this.str = ''
}
}
})

阅读全文 »

js中call与apply的用法及区别

发表于 2018-09-30 | 分类于 前端 | 阅读次数:

在学习mvvm模式的代码编写过程中,用到了js中的call方法,之前在其他的项目代码中也经常会见到call与apply的用法,看了一番资料,用最简单的代码来进行理解
其实call与apply的作用一样,只是传递参数的方式不一样,都是待用某一个函数方法,但是如果这个函数里边有用到this或者跟作用域有关的东西,我们就可以通过call或者apply传入不同的作用域进去(this)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
const obj = {
name: 'xiechao',
age: 28,
getData: function(txt){
// 默认的this是当前对象 obj
console.log(this)
console.log(txt)
}
}
const data = {name:'jordan', age: 26}
obj.getData('原参数')
// 输出{name: "xiechao", age: 28, getData: ƒ}
// 输出 原参数
// 传入另外一个obj作为this,也就是作用于
// call 的参数用函数参数的方式

obj.getData.call(data,'call参数')
// 输出 {name: "jordan", age: 26}
// 输出 call参数
// apply 的参数方式用数组形式

obj.getData.apply(data,['apply参数'])
// 输出 {name: "jordan", age: 26}
// 输出 apply参数

典型引用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
let number = [1,5,3,10]
// 以数组格式传入参数
Math.max.apply(null,number)
Math.min.apply(null,number)
// ES5的继承
function Person(){

}
// call的应用
function Student(){
// 在子类的构造函数中调用一次父类的构造,获得父类的属性
Person.call(this)
}
// 子类原型继承父类的属性及方法
Student.prototype = new Person()
Student.prototype.constructor = Student

在js中,call与apply的还是比较常见的,现在流行的vue,经常会用到this这个参数,但是某些时候你需要传入不同的this指向。

基于webpack4制作项目开发的demo配置(含babel、less等常用开发插件)

发表于 2018-09-28 | 分类于 前端 | 阅读次数:

现在的前端开发基本上都是基于vue或者react的开发,而且大部分都是基于别人已经写好的基础全家桶,已经配置好了webpack、less/sass、babel等等其他插件,但是某些时候需要自己更改webpack配置的话,总避免不了去查issue,有些时候呢,比较简单的页面,又不想用vue/react来写,但是需要用到webpack的打包(可以使用es6、自动打包等等很爽的特性),在写这个demo的时候顺便温习了以下webpack的使用。

项目初始化

新建文件夹 webpack4-demo,然后用npm命令初始化

1
2
3
4
mkdir webpack4-demo
cd webpack4-demo
npm init
# 之后输入一些项目信息

项目开发依赖安装

在构建这个项目的时候需要一些必要和其他辅助类的开发依赖包,比如postcss(可以import或者@import引入css))、autoprefixer(css自动添加浏览器兼容)、babel(es6代码转译,自动天机爱polyfill)、less、uglifyjs(混淆压缩js),在package.json的devDependencies下添加这些依赖。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
"devDependencies": {
"@babel/core": "^7.1.0",
"@babel/plugin-transform-runtime": "^7.1.0",
"@babel/preset-env": "^7.1.0",
"@babel/runtime": "^7.0.0",
"autoprefixer": "^9.1.5",
"babel-loader": "^8.0.2",
"clean-webpack-plugin": "^0.1.19",
"css-loader": "^1.0.0",
"html-webpack-plugin": "^3.2.0",
"less": "^3.8.1",
"less-loader": "^4.1.0",
"postcss-import": "^12.0.0",
"postcss-loader": "^3.0.0",
"style-loader": "^0.23.0",
"uglifyjs-webpack-plugin": "^2.0.1",
"webpack": "^4.20.2",
"webpack-cli": "^3.1.1",
"webpack-dev-server": "^3.1.9",
"webpack-merge": "^4.1.4"
},

项目文件结构设置

在webpack4-demo项目中创建如下的目录结构

各配置文件及路径说明:

1
2
3
4
5
6
7
8
9
10
11
12
config/ # webpack配置文件目录
config/webpack.base.config.js # webpack通用/基础配置
config/webpack.dev.config.js # webpack开发环境下的配置
config/webpack.prod.config.js # webpack 生产环境的配置
dist/ # webpack打包文件的目录
src/ # 源码目录
src/main.js # 入口文件,可自行定义文件名,与webpack中的entry处的配置一致
.babelrc # babel的配置
.editorconfig # 编辑器的配置
.gitignore # git忽略文件
.postcssrc.js # postcss配置插件,如 post-import、autoprefixer等插件
.index.html #html文件结构

package.json是npm项目依赖管理,在文件的底部需要添加如下的autoprefixer的配置

1
2
3
4
5
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
]

阅读全文 »

使用electorn开发google爬虫

发表于 2018-09-20 | 分类于 前端技术 | 阅读次数:

electron介绍

最近接触到 electron 的开发,elctron基于NodeJs以及Chromium(可以看作是一个完整的chrome浏览器),这样就可以在nodejs环境下,开发html界面,并且通过electron提供的api使用本地计算机的资源,最后打包成一个应用程序,包括windows、linux、macos,三个平台兼容的应用程序,因为都是基于nodejs和Chromium,而他们包括electron的兼容都已经帮你做好了,直接用js写代码跑起来即可,最简单就是将一个网页(包含业务操作)打包成软件包。

爬虫工具nightmare介绍

nightmare 是基于electron开源出来的一个代码测试工具,也就是说模拟浏览器操作来测试你的代码,既然nightmare可以模拟浏览器操作,就突然想到是否能用它来模拟浏览器正常的浏览爬取数据,并且不需要研究协议、headers、cookie、ip等等,这些都不需要了,因为现在这就是一个普通的浏览器,当然频率过高还是会有一定的限制,经过一番搜索,nightmare本身并部支持在electron下再运行,但是!
有人fork了nightmare的源码,改出了一个可以在electron下运行的nightmare——eramthgin ,也就是说我们可以用js开发出一个带界面操作的爬虫软件!
理论上你能正常通过浏览器浏览的网站,他的内容你都可以通过nightmare进行获取,比如google,只要你的电脑可以正常访问就没有问题,electron默认就是chrome浏览器,默认代理就是使用的你的电脑设置的代理。

项目结构初始化

  1. 初始化项目
    electron项目基于electron-vue 的vue模板进行初始化,基本上帮你配好了熟悉的vue开发环境。
    1
    2
    3
    4
    # 安装vue-cli 并初始化模板
    npm install -g vue-cli
    # 初始化项目的时候我没选 eslint,暂时跟我的vscode兼容没设置好
    vue init simulatedgreg/electron-vue ele-crawler

package.json 修改,因为taobao没有2.0.10的镜像

1
2
3
4
5
6
7
devDependencies:{
"electron": "^2.0.2"
}
// 修改为
devDependencies:{
"electron": "2.0.9"
}

1
2
3
4
5
6
7
8
9
# 安装依赖运行
cd ele-crawler
# yarn安装比npm更快,设置淘宝镜像
yarn config set sass-binary-site http://npm.taobao.org/mirrors/node-sass
yarn config set ELECTRON_MIRROR https://npm.taobao.org/mirrors/electron
yarn config set registry https://registry.npm.taobao.org
# 安装如果报错的话,删掉node_modules文件夹,执行上面操作再安装,可解决99%的安装依赖报错问题
yarn
yarn run dev

现在electron-vue项目就跑起来了,系统会自动打开浏览器demo窗口。

阅读全文 »

亚马逊AWS服务器上搭建独立的Hexo个人博客

发表于 2018-09-19 | 分类于 Linux | 阅读次数:

最近使用Hexo在Github上部署了个人博客,个人博客地址,使用Hexo部署很方便,写作用markdown语法,本地html全站静态化构建,一条命令直接部署到github上,相当方便,但是有1个问题,就是百度无法收录 Github Pages网站的内容,因为Github把百度爬虫给屏蔽了,正好手上有1个aws服务器,就想着把博客部署到aws也不错,反正一年的免费,其他的云主机(阿里云、腾讯云)都类似,只要是一台独立的主机(VPS即可),那么开始吧!

hexo本地部署

不管怎么样,先在本地跑起来再说

安装hexo

本地需要有 node 环境,全局安装 hexo-cli

1
npm i hexo-cli g

hexo初始化项目

假如需要在D盘新建一个 blog 项目

1
2
3
4
5
6
7
8
9
cd d
# 初始化hexo项目
hexo init blog
# 安装npm依赖
npm i
# 启动hexo,hexo在初始化的时候会自动新建一篇 hello hexo的md文档,在/source/_posts 目录下
hexo s
# 或者以debug模式启动,文章修改后hexo自动重新编译
hexo s --debug

其他hexo的相关配置自行上官网查看即可,不难 hexo文档

阅读全文 »

123
xiaochao

xiaochao

记录技术,分享技术

26 日志
13 分类
22 标签
GitHub
© 2017 — 2020 xiaochao
由 Hexo 强力驱动
|
主题 — NexT.Pisces v5.1.4