精华内容
下载资源
问答
  • 前端部署项目

    万次阅读 2019-07-21 12:33:08
    首先测试上线: 在项目的dev分支上 ...$http-server -c10 //后面的c-10是缓存,可以写,也可以 如果发现这里启动不了,就去项目里找到config目录下的index.js文件,将host配置为0.0.0.0...

    感谢内容提供者:金牛区吴迪软件开发工作室

    首先测试上线:

    1. 在项目的dev分支上
    $ npm run build
    
    1. 在项目dev分支全局安装http-sever
    $ npm i http-server -g
    
    1. 启动http-sever
    $ http-server -c10     //后面的c-10是缓存,可以写,也可以不写
    

    如果发现这里启动不了,就去项目里找到config目录下的index.js文件,将host配置为0.0.0.0

    1. 修改后重新npm run build(第三部可以在建立项目时直接修改)
    2. 进入dist目录
    3. 启动http-server -c10服务器

    正式上线步骤:

    一:远程创建上线分支

    第一种:

    1. 在远程创建一个用于上线的分支(也可以使用本地创建一个分支将其推送到远程仓库)
    2. 如果是使用远程创建了上线的分支,就在本地创建一个相同的分支,建立关联并push上线的代码到远程上线的分支

    第二种:

    1. 简单的方式就是在本地直接创建一个上线分支,基于dev分支将项目上线代码push到远程仓库
    二:购买服务器(如果已购买并配置完成请略过)
    1. 可选择性购买(腾讯云、阿里云等、、、)
    2. 购买成功后首先配置安全组,(在更多 -> 安全组 -> 配置安全组)
      设置入站规则为0.0.0.0(就是默认所有ip地址都可访问该服务器【阿里云服务器是没有默认配置此选项的,腾讯云是默认配置好的】)
      在这里插入图片描述
      如果是阿里云服务器就是 更多 -> 配置安全组 -> 配置规则 -> 快速创建规则 -> 配置以下内容,这里的优先级一定不能与其他配置冲突。
      在这里插入图片描述
    3. 设置密码 - - 重启服务器
      腾讯云设置密码:
      在这里插入图片描述
      阿里云设置密码:
      在这里插入图片描述
    4. 第一种登录方式 - - 使用浏览器方式登录 - - 就会进入服务器命令行
      在这里插入图片描述
      输入ls查看 这个时候会让你输入密码,这个密码就是你第三步设置的密码。
      在这里插入图片描述
      注意:当你输入密码的时候是不会有任何显示的,输入正确即登录成功,输入错误会返回。
      登录成功后就会显示下列命令行
      在这里插入图片描述
      cd/ 查看根目录
    5. 第二种登录服务器方式(常用):随便找个目录 使用命令行
    $ ssh 服务器用户名@服务器公网IP地址
    
    1. 输入密码进入服务器的用户目录
      在这里插入图片描述
    2. 在用户目录下安装nodejs和git
    $ curl -sL https://rpm.nodesource.com/setup_10.x | sudo bash -			//安装更高版本的node
    $ yum install nodejs
    $ yum install git
    

    如果npm不了就是openssl版本低,需要升级

    $ yum update openssl -y
    
    1. 测试服务器是否可被访问
    $ cd /		进入服务器根目录
    $ cd data 		进入data目录(一般都在这个目录创建一个文件夹放项目)
    $ mkdir www			创建文件夹(创建一个www的目录用来存放上线的项目)
    $ mkdir test 		创建上线的项目存放文件夹(名字自行起)
    $ cd test			进入该文件夹
    $
    $//安装以下文件也可在用户目录下直接一次性安装完成
    $ npm install -g http-server
    $ npm install pm2 -g
    $ npm install -g cnpm
    $
    $//启动方式:
    $ http-server -c10		启动服务器
    $//也可以用:
    $ pm2 start http-server		启动服务器
    $ pm2 stop id 		就能停止服务器对该id的响应
    $ pm2 delete id 		从服务器上删除该id
    $ PS:上述俩种都是默认启用8080端口,想要启动其他端口【别忘了配置安全组规则】:
    $ http-server -c10 -p 8081
    $ pm2 start http-server -- -p 8081
    

    小知识:
    http-server ./ -p端口名 指定端口

    1. 部署项目
    $ cd data/www/		进入www目录
    $ git clone -b 远程仓库的上线分支名(远程仓库ssh或https地址)	文件夹的名字		(克隆远程仓库要上线的分支)
    $进入这个项目的文件夹 	cnpm i 安装项目依赖
    $ npm run build
    $ cd dist/		进入dist目录
    $ pm2 start http-server		启动服务器
    

    centOS nginx部署

    $ yum install nginx -y
    

    当安装好之后,就会在 /etc/nginx 目录下,看到有一堆文件,其中 nginx.conf 这个文件就是默认的 nginx 配置文件,下面有一个目录叫conf.d 我们自己写的配置就放在这个目录下。

    如果报错为:

    $ nginx: [error] open() "/run/nginx.pid" failed (2: No such file or directory)
    

    那就先执行:

    $ nginx -t
    $//将得到如下的输出:
    $ nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
    $ nginx: configuration file /etc/nginx/nginx.conf test is successful
    $//再执行:
    $ nginx -c /etc/nginx/nginx.conf
    $ nginx -s reload
    

    这时候直接访问你的公网ip地址,应该就能看到页面显示的是 welcome to nginx

    进入到 /etc/nginx/conf.d 新建一个 任意名字.conf 在里面写入server的配置

    如果没有使用hash router,那么就会刷新之后页面无法访问

    只需要在server配置里加上

    vue-router文档:https://router.vuejs.org/zh/guide/essentials/history-mode.html#%E5%90%8E%E7%AB%AF%E9%85%8D%E7%BD%AE%E4%BE%8B%E5%AD%90

    location / {
      try_files $uri $uri/ /index.html;
    }
    

    解决不能npm run build的问题

    $ sudo /bin/dd if=/dev/zero of=/var/swap.1 bs=1M count=1024
    $ sudo /sbin/mkswap /var/swap.1
    $ sudo /sbin/swapon /var/swap.1
    
    //继续npm run build
    
    展开全文
  • 前端项目与技术实践前端开发规范HTML规范head内容​ head中必须定义title、keyword、description,保证基本的SEO页面关键字和内容描述。移动端页面head要添加viewport控制页面不缩放,有利于提高页面渲染性能。建议...

    前端项目与技术实践

    前端开发规范

    HTML规范

    head内容

    ​ head中必须定义title、keyword、description,保证基本的SEO页面关键字和内容描述。移动端页面head要添加viewport控制页面不缩放,有利于提高页面渲染性能。建议在页面<head>加上基本的社交RICH化消息,保证网页地址分享后能够显示缩放图、图标和描述等。

    <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
    <meta itemprop="name" content="页面标题">
    <meta name="description" itemprop="description" content="页面内容描述">
    <meta itemprop="image" content="http://xxx.com/logo.png">

    img的alt属性

    <img>元素上加alt属性,用利于页面搜索引擎优化,对于盲人用户和图像加载失败的提示很实用(支持无障碍阅读)

    <img src="banner.jpg" alt="宣传图片">

    label的for属性

    label的for属性或者将对应控件放在label标签内部,这样在点击label时,同时会关联到对应的input或textarea上选中,增加了输入的响应区域。

    <label for="blue">蓝色</label><input type="radio" id="blue" name="color" value="#00f">
    <label><input type="radio" name="color" value="#f00">红色</label>

    css规范

    • 书写CSS样式不能用id选择器,因为id选择器很难复用;
    • 如果属性值为0,不需要为0加单位;
    • 先写元素的布局属性position、display、float、overflow等,再写元素的内容属性color、font、text-align等
    • 多种浏览器兼容,先写私有属性、后写标准属性

      .ui-news {
          -webkit-box-shadow: 1px 1px 5px;
          -moz-box-shadow: 1px 1px 5px;
          -ms-box-shadow: 1px 1px 5px;
          -o-box-shadow: 1px 1px 5px;
          box-shadow: 1px 1px 5px;
      }

    JavaScript规范

    条件判断

    不要直接使用undefined进行变量判断。

    // 不推荐
    if(name == undefined) {return false;}
    // 推荐
    if(typeof person === 'undefined') {return false;}

    数组拷贝

    let ary = [1, {a: 2}];
    let ary2 = [...ary];
    let ary3 = {};
    Object.assign(ary3, ary);
    ary[1].a = 3;
    ary2[1].a; // 3
    ary3[1].a; // 3

    注意:都是浅拷贝!!

    数组遍历使用for…of,对象遍历使用for…in

    let ary = ['a', 'b', 'c'];
    let obj = { a: 1, b: 2};
    for(let item of ary) {
      console.log(item);
    }
    for(let key in obj) {
      console.log(`${key}, ${obj[key]}`)
    }

    前端防御性编程规范

    防御性编程是指通过检测任何可能存在的逻辑异常问题的代码实现,提高脚本执行过程健壮性的一种编程手段。

    // 不推荐
    t = data.userInfo.name;
    // 推荐
    t = data && data.userInfo && data.userInfo.name || 'ligang';

    通过&&或者||进行检测,这也是函数式编程所提倡的!

    前端组件规范

    所谓的组件通常是指采用代码管理中的分治思想,将复杂的项目代码结构拆分成多个独立、简单、解耦合的结构或文件的形式进行分开管理,达到让项目代码和模块更加清晰的目的,而组件规范则是我们进行拆分、组织、管理项目代码方法的一种约定。不同的是,开发规范关注文件内部代码级别的一致性,组件规范则更关注项目中业务功能模块内容组织的一致性。任何一个独立的功能模块之间都应该是无耦合并能和其他模块很好对接和组合!

    UI组件规范

    (1)UI层风格统一化,相同功能的模块在相同场景下结构层和表现层应该一致;(2)增加UI层复用性;(3)更符合用户的体验习惯;(4)增加了开发规范的统一性。

    模块化规范

    JavaScript文件之间互相依赖引用的一种通用语法约定,即按照一定规范写JavaScript,方便被其他JavaScript文件引用。主要包括AMD(Asynchronous Module Definition,异步模块定义)、CMD(Common Module Definition,通用模块定义)、CommonJS、import/export等。参考:前端模块系统

    项目组件化设计规范

    为了实现对复杂的项目进行管理,我们通常使用组件,目前实现组件化的方案也越来越多:Web Component组件化、MVVM框架组件化(通常,将页面中的模块按照元素来划分,并将模块相关的描述语法、CSS样式、执行脚本放在同一个文件里进行引用)、基于Virtual DOM框架的组件化、直接基于目录管理的组件化等。

    自动化构建

    自动化构建时基于项目代码文件级的分析处理。

    这里写图片描述

    注意,为了保证首屏加载的资源最小化,非首屏内容希望通过JavaScript来异步渲染,这就需要构建工具能将非首屏的组件打包成异步资源,以按需或异步的方式加载。在开发中,我们通常不希望关注异步与同步组件的区别,所以通过将异步组件放在异步的目录里进行单独打包或者加入特殊的标识。

    以require的引用方式为例,了解一下JavaScript组件模块文件的依赖分析过程:

    1. 从入口模块开始分析require函数调用依赖;
    2. 根据依赖生成JavaScript AST(Abstract Syntax Tree,抽象语法树,将JavaScript代码映射成一个树形结构的JSON对象树)
    3. 根据AST找到每个模块的模块名;
    4. 得到每个模块的依赖关系,生成一个依赖字典;
    5. 根据模块化引用机制包装每个模块,传入依赖字典以及import或require函数,生成执行的JavaScript代码。

    前端性能优化

    用户获取页面数据或执行某个页面动作的一个实时性指标,一般以用户希望获取数据的操作到用户实际获得数据的时间间隔来衡量。用户的等待延迟可分为两部分:可控等待延时(资源大小、HTTP数量等)和不可控等待延时(鼠标点击延时、CPU计算延时、ISP网络传输延时等)

    performance Timing API

    用于记录页面加载和解析过程中关键时间点的机制,它可以详细记录每个页面资源从开始加载到解析完成这一过程中具体操作发生的时间点。(图片引自:https://w3c.github.io/navigation-timing/

    这里写图片描述

    // 加载时间耗时(整体)
    performance.timing.loadEventEnd - performance.timing.navigationStart;
    // 针对单个资源
    let p = performance.getEntriesByName("https://www.baidu.com/");
    p[0].responseEnd - p[0].requestStart; //204.175 Request请求耗时
    p[0].domComplete - p[0].domInteractive; // 490.56999999999994 解析DOM树耗时
    p[0].loadEventEnd - p[0].loadEventStart; // 35.955000000000155 Load事件消耗

    这里写图片描述

    参考资料:https://www.w3.org/TR/2017/CR-resource-timing-1-20170330/

    Profile工具

    Profile用来测试页面脚本运行时系统内存和CPU资源占用情况的API,可以获得如下几个信息:

    • 分析页面脚本执行过程中最消耗资源的操作;
    • 记录页面脚本执行过程中JavaScript对象消耗的内存与堆栈的使用情况;
    • 检测页面脚本执行过程中CPU占用情况。
    console.profile();
    document.querySelector('#content').innerHTML = '棒棒';
    calc();
    function calc() {
      let result = null;
      for(let i = 0; i < 100000; i++) {
        result += i;
      }
      return result;
    }
    console.profileEnd();

    Profile示例

    资源加载时序图

    通过时序图可以确保文件加载顺序的情况,查看是否存在十分耗时的阻塞页面展示的资源加载。

    文件资源时序图

    桌面浏览器前端优化策略

    • 避免页面中空的href和src:浏览器在渲染的过程中仍会将href属性或src属性中的空内容进行加载,直至失败,这样会阻塞页面中其他资源的下载进程;
    • 为HTML指定Cache-Control或Expires:在页面Cache-Control或Expires头部有效时,浏览器将直接从缓存中读取内容,不向服务器发送请求;
    • 减少页面重定向:一次重定向大约需要600毫秒的时间开销;
    • 将静态资源分域存放来增加并行下载数:同一时刻向同一域名请求文件的并行下载数是有限的,因此可以使用多个域名的主机来存放不同的静态资源,同时可以隔离Cookie,减少了请求头大小
    • 使用CDN Combo下载传输内容:复用HTTP连接,将多个文件请求打包成一个文件的形式来返回,以减少HTTP请求数;

      <script src="//cdn.xxx.com/path/a.js,b.js,c.js"></script>
    • 缩小favicon.ico并缓存:一般Web应用的favicon.ico是很少改变的;
    • 推荐使用异步JavaScript资源:使用async时,加载和渲染后续文档元素的过程和main.js的加载和执行是并行的;使用defer时,加载后续文档元素的过程和面.js的加载是并行的,但是main.js的执行要在页面所有元素解析完成之后才开始执行;

      <script src="main.js" defer></script>
      <script src="main.js" async></script>
    • 避免使用CSS import引用加载CSS:因为这样会增加CSS资源加载的关键路径长度,代用@import的CSS样式需要在CSS文件串行解析到@import时才会加载另外的CSS文件,大大延后CSS渲染完成的时间;
    • CSS放到<head>中,JavaScript放到<HTML>文档底部:这样可以尽早完成页面渲染,同时防止JavaScript的加载和解析执行对页面渲染造成阻塞;
    • 尽量避免使用<table><iframe>等慢元素:<table>内容的渲染是将table的DOM渲染树全部生成完并一次性绘制到页面上;iframe内资源的下载进程会阻塞父页面静态资源的下载与CSS及HTML DOM的解析,尽量使用异步的方式动态添加iframe;

    移动端浏览器前端优化策略

    • 确保首屏内容最小化:首屏所有资源大小不超过1MB;
    • inline首屏必备的CSS和JavaScript:将首屏加载的CSS和JavaScript内联到页面中;
    • meta dns prefetch 设置DNS预解析:让浏览器提前解析获取静态资源的主机IP;

      <meta http-equiv="x-dns-prefetch-control" content="on">
      <link rel="dns-prefetch" href="//cdn.domain.com">
    • **合理利用MTU策略:**TCP网络传输最大传输单位(Maximum Transmission Unit,MTU)为1500B,即一个RTT(Round-Trip Time,网络请求往返时间)内可以传输的数据量最大为1500字节,因此尽量保证页面HTML内容控制在1KB内;
    • 合理使用base64内嵌图片:较小的图片可以使用base64嵌入到HTML页面或CSS中,大于2KB不推荐使用base64;

      .class-name {
      background-image: url('data:image/png;base64,iVboR...');
      }
    • 尽量使用事件代理,避免直接事件绑定: 使用事件代理可以避免对每个元素都进行绑定,并且可以避免出现内存泄漏及需要动态添加元素的事件绑定问题;
    • **使用touchstart代替click:**touchstart事件和click事件触发时间之间存在300毫秒的延时;
    • 避免touchmove、scroll连续事件处理:应该使用节流函数,可参照debounce与throttle区别
    • 不要滥用float:使用float的元素布局计算比较消耗性能;
    • **尝试使用SPDY和HTTP2:**SPDY基于TCP,对HTTP的增强版(多路复用,请求优先级,HTTP报头压缩);

    前端用户数据分析

    因为目前从事的公司Ptmind就是在做用户数据分析,自己也是Ptengine采集器的主力,所以后续有时间单独进行描述!

    前端日志上报

    浏览器提供了try…catch和window.onerror两种机制来帮助我们获取用户页面的脚本错误信息。window.onerrorl可捕获脚本语法错误和运行时错误,但对于报错的JavaScript和HTML不在同一域名下,获得的错误都是script error,可以通过<scritp src="//otherDomain.com/main.js" crossorigin></script>来获取具体信息。

    window.onerror = function(messageOrEvent, source, lineno, colno, error) {
        console.log(messageOrEvent, source, lineno, colno, error);
        return true;    // 彻底忽略所有错误
    };

    捕获到错误后,我们需要根据一定的概率进行上报(如果将所有错误进行上报会占用日志收集服务器的很多资源和流量),通常我们可以进行封装log.log,在开发环境中直接使用console.log/error,在生产环境使用XMLHttpRequest。总之,我们需要根据实际情况指定,千万不可过度设计

    前端搜索引擎优化

    • 一定要定义title、keywords、description:多个title值使用分隔符(“_”、“-”、“ ”、“,”),确保每个页面的title是对一无二的;
    • 每个页面都有一个唯一的H1,同时所有的img都有alt属性:<h1>作为页面最高层的标题通常容易被搜索引擎收录;
    • 如果URL发生改变,一定要使旧地址301指向新的页面,否则搜索引擎会把这个当成死链处理
    • canonical:通常会将下面当做3个地址当做3个页面

      //:domain.com/index.html
      //:domain.com/index.html?from=123
      //:domain.com/index.html?form=456

      可以在<head>上加上canonical声明,告诉浏览器将按照这个href进行收录

      <link rel="cononical" href="//:domain.com/index.html" />
    • 将robots.txt放置站点根目录,禁止抓取网站某些内容
    • sitemap.html或sitemap.xml列出所有URL,便于搜索引擎获取

    前端协作

    明确、合理、可行、性价比、风险。做团队技术驱动者和突破者!

    展开全文
  • 前端路由的基本原理、使用 history 路由模式时后端登录拦截器的配置、Vuex 的引入以及前端拦截器的实现。

    前言

    这一篇主要讲前端路由与登录拦截器的实现。放在一起讲是因为我在开发登录拦截器时因为这个路由的问题遇到了很多坑,花费了很长时间,网上的解决方案都不怎么靠谱,综合了好几种办法才最终成功,其实关于这个部分能写两三篇文章,名字起好了还能多很多访问量,不过为了保证文章的质量我没有这么做,毕竟我不是大神,如果再不用点心,写出来的文章自己都不想再看第二遍,更别提能对大家有所帮助了。

    一、前端路由

    大家如果留心观察就会发现,之前我们做的页面的 URL 里有一个 # 号,这个 # 号有什么含义呢?

    假设在 html 中有这么一段代码:<div id="test">This is a test</div>,如果我们想让页面定位到这个 div 所在的位置,可以加一个超链接 <a herf="#test">Jump to test</a>,这里的 # 被称为“锚点”,点击超链接,可以发现网页的 URL 发生了变化,但页面并不会跳转。

    在互联网流量如此庞大的今天,我们需要想办法后端服务器的压力,利用 AJAX,我们可以不重载页面就刷新数据,如果再加上 # 号的特性(即改变 URL 却不请求后端),我们就可以在前端实现页面的整体变化,而不用每次都去请求后端。

    为了实现前端路由,我们可以监听 # 号后面内容的变化(hashChange),从而动态改变页面内容。URL 的 # 号后面的地址被称为 hash ,估计是哪个大神拍脑袋想的,不用深究。这种实现方式我们称之为 Hash 模式,是非常典型的前端路由方式。

    另一种常用的方式被称为 History 模式,这种方式使用了 History APIHistory API 顾名思义就是针对历史记录的 API ,这种模式的原理是先把页面的状态保存到一个对象(state)里,当页面的 URL 变化时找到对应的对象,从而还原这个页面。其实原本人家这个功能是为了方便浏览器前进后退的,不得不说程序员们的脑洞真大。使用了这种模式,就可以摆脱 # 号实现前端路由。

    Vue 已经为我们提供了两种模式的前端路由,无需我们自己去实现。

    二、使用 History 模式

    首先我们把 Vue 中配置的路由从默认的 hash 模式切换为 histroy 模式。打开我们的前端项目 wj-vue,修改 router\index.js,加入 mode: 'history 这句话。整体代码如下:

    import Vue from 'vue'
    import Router from 'vue-router'
    import AppIndex from '@/components/home/AppIndex'
    import Login from '@/components/Login'
    
    Vue.use(Router)
    
    export default new Router({
      mode: 'history',
      routes: [
        {
          path: '/login',
          name: 'Login',
          component: Login
        },
        {
          path: '/index',
          name: 'AppIndex',
          component: AppIndex
        }
      ]
    })
    

    运行项目,访问不加 # 号的 http://localhost:8080/login ,成功加载页面。

    接下来,我们把前端打包后部署在后端。这不是前后端分离项目推荐的做法,之前我们讲过其实应该把前后端分别部署在不同的服务器中,但实际上仍有不少项目会选择把前后端整合在一起,只使用一个服务器,所以这里我们也提及一下这种方式,但在之后的开发中不会这样部署。

    先在项目目录执行 npm run build,控制台输出如下内容表明执行完毕:
    在这里插入图片描述
    这时在项目的 dist 文件夹下生成了 static 文件夹和 index.html 文件,把这两个文件,拷贝到我们后端项目的 wj\src\main\resources\static 文件夹下,一定要注意这个位置,这时后端配置的静态文件的 path,虽然看起来很诡异,但一般都不作修改。
    在这里插入图片描述
    接下来,打开后端项目并运行,访问 http://localhost:8443/index.html ,(注意输入后缀 .html)发现页面是空白的,但确实取到了这个页面,再访问 http://localhost:8443/login ,发现跳转到了错误页面(White Error Page)。
    在这里插入图片描述
    这里我们回顾一下单页面应用的概念,在我们这个项目中,其实只有 index.html 这一个页面,所有的其它内容都是在这个页面里动态渲染的。当我们直接在后端访问 /login 路径时,服务器会后端并没有这个路径对应的内容,所以返回了 Error Page。

    为了获取到我们需要的内容,我们要想办法触发前端路由,即在后端添加处理内容,把 通过这个 URL 渲染出的 index.html 返回到浏览器。

    在后端项目中新建一个 package 名为 error,新建实现 ErrorPageRegistrar 接口的类 ErrorConfig,把默认的错误页面设置为 /index.html,代码如下

    package com.evan.wj.error;
    
    import org.springframework.boot.web.server.ErrorPageRegistrar;
    import org.springframework.boot.web.server.ErrorPage;
    import org.springframework.boot.web.server.ErrorPageRegistry;
    import org.springframework.http.HttpStatus;
    import org.springframework.stereotype.Component;
    
    @Component
    public class ErrorConfig implements ErrorPageRegistrar {
    
        @Override
        public void registerErrorPages(ErrorPageRegistry registry) {
            ErrorPage error404Page = new ErrorPage(HttpStatus.NOT_FOUND, "/index.html");
            registry.addErrorPages(error404Page);
        }
    
    }
    

    重新启动项目,访问 http://localhost:8443/login ,成功进入登录页面。

    三、后端登录拦截器

    为了完善登录功能,我们需要限制未登录状态下对核心功能页面的访问。登录拦截可以由多种方式来实现,我们首先讲解后端拦截器的开发。(注意如果没有把前后端项目整合起来,就没有办法使用这种方式)

    一个简单拦截器的逻辑如下:

    1.用户访问 URL,检测是否为登录页面,如果是登录页面则不拦截
    2.如果用户访问的不是登录页面,检测用户是否已登录,如果未登录则跳转到登录页面

    1.LoginController

    首先我们修改 LoginController 的内容。之前我们实现了通过查询数据库验证用户名是否正确,但仅此而已。

    为了保存登录状态,我们可以把用户信息存在 Session 对象中(当用户在应用程序的 Web 页之间跳转时,存储在 Session 对象中的变量不会丢失),这样在访问别的页面时,可以通过判断是否存在用户变量来判断用户是否登录。这是一种比较简单的方式,感兴趣的同学可以尝试别的方法。

    修改后的代码内容如下:

    package com.evan.wj.controller;
    
    import com.evan.wj.pojo.User;
    import com.evan.wj.result.Result;
    import com.evan.wj.service.UserService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.*;
    import org.springframework.web.util.HtmlUtils;
    
    import javax.servlet.http.HttpSession;
    
    @Controller
    public class LoginController {
    
        @Autowired
        UserService userService;
    
        @CrossOrigin
        @PostMapping(value = "/api/login")
        @ResponseBody
        public Result login(@RequestBody User requestUser, HttpSession session) {
            String username = requestUser.getUsername();
            username = HtmlUtils.htmlEscape(username);
    
            User user = userService.get(username, requestUser.getPassword());
            if (null == user) {
                return new Result(400);
            } else {
                session.setAttribute("user", user);
                return new Result(200);
            }
        }
    }
    
    

    其实只是添加了一条语句 session.setAttribute("user", user);

    2.LoginInterceptor

    新建 package 名为 interceptor,新建类 LoginInterceptor

    Interceptor 即拦截器,在 Springboot 我们可以直接继承拦截器的接口,然后实现 preHandle 方法。preHandle 方法里的代码会在访问需要拦截的页面时执行。

    代码如下:

    package com.evan.wj.interceptor;
    
    import com.evan.wj.pojo.User;
    import org.apache.commons.lang.StringUtils;
    import org.springframework.web.servlet.HandlerInterceptor;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    
    public class LoginInterceptor  implements HandlerInterceptor{
    
        @Override
        public boolean preHandle (HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
            HttpSession session = httpServletRequest.getSession();
            String contextPath=session.getServletContext().getContextPath();
            String[] requireAuthPages = new String[]{
                    "index",
            };
    
            String uri = httpServletRequest.getRequestURI();
    
            uri = StringUtils.remove(uri, contextPath+"/");
            String page = uri;
    
            if(begingWith(page, requireAuthPages)){
                User user = (User) session.getAttribute("user");
                if(user==null) {
                    httpServletResponse.sendRedirect("login");
                    return false;
                }
            }
            return true;
        }
    
        private boolean begingWith(String page, String[] requiredAuthPages) {
            boolean result = false;
            for (String requiredAuthPage : requiredAuthPages) {
                if(StringUtils.startsWith(page, requiredAuthPage)) {
                    result = true;
                    break;
                }
            }
            return result;
        }
    }
    
    

    看起来似乎比较长,其实就是判断 session 中是否存在 user 属性,如果存在就放行,如果不存在就跳转到 login 页面。这里使用了一个路径列表(requireAuthPages),可以在里面写下需要拦截的路径。当然我们也可以拦截所有路径,那样就不用写这么多了,但会有逻辑上的问题,就是你访问了 \login 页面,仍然会需要跳转,这样就会引发多次重定向问题。

    3.WebConfigurer

    我们写完了拦截器,但是它却并不会生效,因为我们还没有把它配置到项目中。

    新建 package 名为 config,新建类 MyWebConfigurer,代码如下:

    package com.evan.wj.config;
    
    import com.evan.wj.interceptor.LoginInterceptor;
    import org.springframework.boot.SpringBootConfiguration;
    import org.springframework.context.annotation.Bean;
    import org.springframework.web.servlet.config.annotation.*;
    
    @SpringBootConfiguration
    public class MyWebConfigurer implements WebMvcConfigurer {
    
        @Bean
        public LoginInterceptor getLoginIntercepter() {
            return new LoginInterceptor();
        }
    
        @Override
        public void addInterceptors(InterceptorRegistry registry){
            registry.addInterceptor(getLoginIntercepter()).addPathPatterns("/**").excludePathPatterns("/index.html");
        }
    }
    
    

    通过这个配置类,我们添加了之前写好的拦截器。这里有一句非常重要的语句,即

    registry.addInterceptor(getLoginIntercepter()).addPathPatterns("/**").excludePathPatterns("/index.html");
    

    这条语句的作用是对所有路径应用拦截器,除了 /index.html

    之前我们在拦截器 LoginInterceptor 中配置的路径,即 index,触发的时机是在拦截器生效之后。也就是说,我们访问一个 URL,会首先通过 Configurer 判断是否需要拦截,如果需要,才会触发拦截器 LoginInterceptor,根据我们自定义的规则进行再次判断。

    /index/index.html 是不同的,也就是说 /index 会触发拦截器而 /index.html 不会,但根据拦截器 LoginInterceptor 中我们定义的判断条件,以 /index 开头的路径都会被转发,包括 index.html

    因为我们做的是单页面应用,之前通过配置 ErrorPage,实际上访问所有路径都会重定向到 /index.html 。我们直接在浏览器地址栏输入 /index 会触发拦截器,经过拦截器重定向到 /login,然后 /login 再经过 Configurer 的判断,再次触发拦截器,由于不在需要拦截的路径中,所以被放行,页面则重新定向到了 /index.html,如果没有再 Configurer 中取消对 /index.html 的拦截,则会再次触发拦截器,再次重定向到 /login,引发如下错误。
    在这里插入图片描述
    上述过程比较绕,这是我开发时的失误,但我觉得恰好可以帮助大家理解拦截器与单页面应用,所以保留了下来。

    4.效果检验

    运行后端项目,访问 http://localhost:8443/index ,发现页面自动跳转到了 http://localhost:8443/login ,输入用户名和密码登录,跳转到 http://localhost:8443/index , 这时可以把浏览器标签关掉,再在一个新标签页输入 http://localhost:8443/index ,发现不会被拦截。

    四、Vuex 与前端登录拦截器

    前面我们使用了后端拦截器,但这种拦截器只有在将前后端项目整合在一起时才能生效,而前后端分离的项目实际上不推荐这么做,接下来我们尝试用前端实现相似的功能。

    实现前端登录器,需要在前端判断用户的登录状态。我们可以像之前那样在组件的 data 中设置一个状态标志,但登录状态应该被视为一个全局属性,而不应该只写在某一组件中。所以我们需要引入一个新的工具——Vuex,它是专门为 Vue 开发的状态管理方案,我们可以把需要在各个组件中传递使用的变量、方法定义在这里。之前我一直没有使用它,所以在不同组件传值的问题上十分头疼,要写很多多余的代码来调用不同组件的值,所以推荐大家从一开始就去熟悉这种管理方式。

    1.引入 Vuex

    在我们的项目文件夹中,运行 npm install vuex --save,之后,在 src 目录下新建一个文件夹 store,并在该目录下新建 index.js 文件,在该文件中引入 vue 和 vuex,代码如下:

    import Vue from 'vue'
    import Vuex from 'vuex'
    
    Vue.use(Vuex)
    

    之后,我们在 index.js 里设置我们需要的状态变量和方法。为了实现登录拦截器,我们需要一个记录用户信息的变量。为了方便日后的扩展(权限认证等),我们使用一个用户对象而不是仅仅使用一个布尔变量。同时,设置一个方法,触发这个方法时可以为我们的用户对象赋值。完整的代码如下:

    import Vue from 'vue'
    import Vuex from 'vuex'
    
    Vue.use(Vuex)
    
    export default new Vuex.Store({
      state: {
        user: {
          username: window.localStorage.getItem('user' || '[]') == null ? '' : JSON.parse(window.localStorage.getItem('user' || '[]')).username
        }
      },
      mutations: {
        login (state, user) {
          state.user = user
          window.localStorage.setItem('user', JSON.stringify(user))
        }
      }
    })
    

    这里我们还用到了 localStorage,即本地存储,在项目打开的时候会判断本地存储中是否有 user 这个对象存在,如果存在就取出来并获得 username 的值,否则则把 username 设置为空。这样我们只要不清除缓存,登录的状态就会一直保存。

    2.修改路由配置

    为了区分页面是否需要拦截,我们需要修改一下 src\router\index.js,在需要拦截的路由中加一条元数据,设置一个 requireAuth 字段如下:

        {
          path: '/index',
          name: 'AppIndex',
          component: AppIndex,
          meta: {
            requireAuth: true
          }
        }
    

    完整的 index.js 代码如下:

    import Vue from 'vue'
    import Router from 'vue-router'
    import AppIndex from '@/components/home/AppIndex'
    import Login from '@/components/Login'
    
    Vue.use(Router)
    
    export default new Router({
      mode: 'history',
      routes: [
        {
          path: '/login',
          name: 'Login',
          component: Login
        },
        {
          path: '/index',
          name: 'AppIndex',
          component: AppIndex,
          meta: {
            requireAuth: true
          }
        }
      ]
    })
    
    

    3.使用钩子函数判断是否拦截

    钩子函数及在某些时机会被调用的函数。这里我们使用 router.beforeEach(),意思是在访问每一个路由前调用。

    打开 src\main.js ,首先添加对 store 的引用

    import store from './store'
    

    并修改 Vue 对象里的内容

    new Vue({
      el: '#app',
      render: h => h(App),
      router,
      // 注意这里
      store,
      components: { App },
      template: '<App/>'
    })
    

    接着写 beforeEach() 函数

    router.beforeEach((to, from, next) => {
        if (to.meta.requireAuth) {
          if (store.state.user.username) {
            next()
          } else {
            next({
              path: 'login',
              query: {redirect: to.fullPath}
            })
          }
        } else {
          next()
        }
      }
    )
    

    这个的逻辑很简单,首先判断访问的路径是否需要登录,如果需要,判断 store 里有没有存储 user 的信息,如果存在,则放行,否则跳转到登录页面,并存储访问的页面路径(以便在登录后跳转到访问页)。

    完整的 main.js 代码如下:

    import Vue from 'vue'
    import App from './App'
    import router from './router'
    import store from './store'
    import ElementUI from 'element-ui'
    import 'element-ui/lib/theme-chalk/index.css'
    
    var axios = require('axios')
    axios.defaults.baseURL = 'http://localhost:8443/api'
    Vue.prototype.$axios = axios
    Vue.config.productionTip = false
    
    Vue.use(ElementUI)
    
    router.beforeEach((to, from, next) => {
        if (to.meta.requireAuth) {
          if (store.state.user.username) {
            next()
          } else {
            next({
              path: 'login',
              query: {redirect: to.fullPath}
            })
          }
        } else {
          next()
        }
      }
    )
    
    /* eslint-disable no-new */
    new Vue({
      el: '#app',
      render: h => h(App),
      router,
      store,
      components: { App },
      template: '<App/>'
    })
    
    

    4.修改 Login.vue

    之前的登录组件中,我们只是判断后端返回的状态码,如果是 200,就重定向到首页。在经过前面的配置后,我们需要修改一下登录逻辑,以最终实现登录拦截。

    修改后的逻辑如下:

    1.点击登录按钮,向后端发送数据
    2.受到后端返回的成功代码时,触发 store 中的 login() 方法,把 loginForm 对象传递给 store 中的 user 对象
    (*这里只是简单的实现,在后端我们可以通过用户名和密码查询数据库,获得 user 表的完整信息,比如用户昵称、用户级别等,返回前端,并传递给 user 对象,以实现更复杂的功能)
    3.获取登录前页面的路径并跳转,如果该路径不存在,则跳转到首页

    修改后的 login() 方法如下:

    login () {
      var _this = this
      console.log(this.$store.state)
      this.$axios
        .post('/login', {
          username: this.loginForm.username,
          password: this.loginForm.password
        })
        .then(successResponse => {
          if (successResponse.data.code === 200) {
            // var data = this.loginForm
            _this.$store.commit('login', _this.loginForm)
            var path = this.$route.query.redirect
            this.$router.replace({path: path === '/' || path === undefined ? '/index' : path})
          }
        })
        .catch(failResponse => {
        })
    }
    

    完整的 Login.vue 代码如下:

    <template>
      <body id="poster">
        <el-form class="login-container" label-position="left"
                 label-width="0px">
          <h3 class="login_title">系统登录</h3>
          <el-form-item>
            <el-input type="text" v-model="loginForm.username"
                      auto-complete="off" placeholder="账号"></el-input>
          </el-form-item>
          <el-form-item>
            <el-input type="password" v-model="loginForm.password"
                      auto-complete="off" placeholder="密码"></el-input>
          </el-form-item>
          <el-form-item style="width: 100%">
            <el-button type="primary" style="width: 100%;background: #505458;border: none" v-on:click="login">登录</el-button>
          </el-form-item>
        </el-form>
      </body>
    </template>
    
    <script>
    
      export default {
        name: 'Login',
        data () {
          return {
            loginForm: {
              username: 'admin',
              password: '123'
            },
            responseResult: []
          }
        },
        methods: {
          login () {
            var _this = this
            console.log(this.$store.state)
            this.$axios
              .post('/login', {
                username: this.loginForm.username,
                password: this.loginForm.password
              })
              .then(successResponse => {
                if (successResponse.data.code === 200) {
                  // var data = this.loginForm
                  _this.$store.commit('login', _this.loginForm)
                  var path = this.$route.query.redirect
                  this.$router.replace({path: path === '/' || path === undefined ? '/index' : path})
                }
              })
              .catch(failResponse => {
              })
          }
        }
      }
    </script>
    
    <style>
      #poster {
        background:url("../assets/eva.jpg") no-repeat;
        background-position: center;
        height: 100%;
        width: 100%;
        background-size: cover;
        position: fixed;
      }
      body{
        margin: 0px;
      }
      .login-container {
        border-radius: 15px;
        background-clip: padding-box;
        margin: 90px auto;
        width: 350px;
        padding: 35px 35px 15px 35px;
        background: #fff;
        border: 1px solid #eaeaea;
        box-shadow: 0 0 25px #cac6c6;
      }
      .login_title {
        margin: 0px auto 40px auto;
        text-align: center;
        color: #505458;
      }
    
    </style>
    
    

    5.效果检验

    同时运行前后端项目,访问 http://localhost:8080/index ,发现页面直接跳转到了 http://localhost:8080/login?redirect=%2Findex

    在这里插入图片描述
    输入账号密码后登录,成功跳转到 http://localhost:8080/index ,之后再次访问则无需登录(除非清除缓存)。


    最后吐槽两句,人呐,真是不能乱立 flag,写第一篇文章的时候,我说感谢老板不让我 996,然后就 895 了,上一篇文章我说这两天闲,多写几篇文章,然后就又接了个大项目,周末还在出差开会,昨天晚上忙到 12 点困得不行,想着先睡觉早上早点起来再把工作收个尾,结果酒店隔壁房间一群小孩儿在玩狼人杀,回想起我们过去同样的行径,这口气我忍了。。。

    所以读者大人们请原谅我没有及时更新,作为一个不知名博主,十分感谢大家的支持。我会坚持下去的,希望大家都能坚持做自己想做的事,一起变得更加牛批!

    查看系列文章目录:
    https://learner.blog.csdn.net/article/details/88925013

    上一篇:Vue + Spring Boot 项目实战(五):使用 Element 辅助前端开发

    下一篇: Vue + Spring Boot 项目实战(七):导航栏与图书页面设计

    展开全文
  • vue前端项目的结构以及组成部分

    千次阅读 2019-07-02 15:01:11
    这也是对前端项目文件组成和几个大的模块的一些介绍,文末还有一些不成文的代码规范 本文目录 项目代码组成 前端项目组成 前端重要的一些库 前端的几大模块 项目编写规范 项目代码组成 先不谈前端项目,结合后端...

    本文结构

    1. 在初入前端的时候,一个项目中的文件夹会非常多,与Vue官网的简单demo相差非常大
    2. 这也是对前端项目文件组成和几个大的模块的一些介绍,文末还有一些不成文的代码规范

    本文目录

    1. 项目代码组成
    2. 前端项目组成
    3. 前端的几大模块
    4. 项目编写规范

    项目代码组成

    1. 先不谈前端项目,结合后端项目来看,项目之所以不是一个单纯的文件,很重要的思想就是,模块化和团队合作
    2. 编程中的模块化衍生出来的就是将不同功能的代码进行分类,放到不同的文件中,需要时再通过引入,拼接相应的功能,从这个角度出发,就能解释为什么会有这么多的文件夹,而且还是一层又一层的文件夹
    3. 还有就是为了和别人合作,需要将不同的功能隔离开来,进行并行开发,这样不同功能之间的耦合性会减少,项目结构是为了可持续开发,而不是随便写了一个文件,功能上虽然实现了,但维护起来甚是头疼,为了考虑方便维护和以后的功能的拓展,也是项目结构如此复杂的一个重要因素

    项目结构的普遍特点

    1. 经常编写的文件通常在最底层,最深处
    2. 放在外面的文件却一般不怎么动
    3. 分工协作的话,分给你的代码通常只在一个小文件中编写
    4. 不懂项目结构也可以完成功能,但是懂会让你有更深的理解
    5. 除了自己功能的文件夹外,一般会有一个像总理一样的文件,管理所有功能

    前端项目组成

    1. vue、react、angular三大前端框架的结构各有不同

    Vue 开源项目结构

    在这里插入图片描述

    React 开源项目结构

    在这里插入图片描述

    Angular 开源项目结构

    在这里插入图片描述

    前端项目组成部分

    1. src 目录,是source 资源的简写,该文件夹是主要编写功能的地方
    2. static 目录,意为静止,静态,也就是存放html页面和图片等的静态文件夹
    3. .gitignore 文件,该文件是给 git 使用,用来选择哪些文件不要被git控制
    4. README.md 文件,GitHub的仓库介绍,使用markdown格式编写,github会把这个文件放在目录下面,并展示出来
    5. package.json 文件,该文件存储的是整个项目的依赖库的信息,还有npm 的一些设置,可以认为该文件是整个项目的最基础的配置文件
    6. package-lock.json 文件,该文件是package.json的辅助文件,用来记录更加详细的依赖库版本和库与库之间的关系,两者组合使用

    Vue 前端项目结构

    在这里插入图片描述

    前端的几大模块

    1. npm

    1. npm 是一个前端库的管理工具,与多数语言的包管理工具一样,功能相似,一般配有一个远程的官方的地方,包含所有的库
    2. npm 是nodejs的一个组成部分,nodejs 和 javascript 的关系
    3. nodejs 是一个解释器,也可以理解为一个javascript 的运行环境,浏览器自带一个解释器,不同的浏览器的解释器不同,chrome谷歌浏览器使用的是V8引擎,nodejs 是基于V8进行增强,舍弃了一些对浏览器的操作,增加了后端处理的功能
    4. nodejs需要安装到电脑中,方可使用

    2. Typescript,ES6 ,Javascript

    1. typescript 是一种增强类型的面向对象的javascript语言,使用typescript的编译器可以将typescript翻译成JavaScript的代码,实质上都是javascript,不过是换了一种方式编写而已
    2. ES6, 全名为 ECMAScript6, 准确地来说,JavaScript是ECMAScript的别名,因为ECMAScript更加官方,感兴趣可以了解js 和ES的渊源
    3. 现在主流的javascript是ES5,ES6就是ES5的升级版本,现在主流的框架都是基于ES6进行开发,但ES6比较先进,很多浏览器还不支持,所以需要Babel库进行翻译,将ES6的代码翻译成ES5,然后再在浏览器上运行
    4. ES6 是JavaScript的重大更新,有兴趣可以继续了解ES6的语法

    3. webpack

    1. 推荐观看视频,有一些前端基础的立马就知道用来干嘛的
    2. webpack 是为了解决文件引入过多,且不能通过编程来控制引入的库的问题的,以前为了引入js 文件需要写多个script标签,引入css文件需要写很多个style标签,但使用webpack将多个js文件和css文件打包在一个文件内,这样html页面就只需要引入一个文件
    3. 当然webpack的功能还不止这些,需要自行学习

    4. eslint

    1. eslint 是一个代码风格检查工具,帮助团队协助时规范不同人员代码编写,可以强制控制代码结构

    5. babel

    1. babel 是为了解决es6和浏览器不兼容的问题而诞生的,将ES6翻译为ES5,使得代码与浏览器能够兼容

    6. css 相关的库

    1. less
    2. sess
    3. 两者都是对css进行改造,让css能够使用变量,流程控制语句等,像编程一样编写css,模块化设计

    以上的这些,除css相关的以外,每一个都有相应的配置文件,学习这些需要有很多基础,基础打牢了才能走得更远

    项目编写规范

    1. 在此处,eslint 需要重点强调,因为如果不会的话,eslint能从四面八方提醒你,叫你在某一行多加一个空格,异常难受

    eslint 的主要功能

    1. 比javasript更严格的语法检查
    2. 各种标点符号,空格,缩进等代码风格的检查
    3. 使用插件控制不同前端框架的特定语法
    4. 恶心你

    如何关闭它

    1. 直接在文件的开头使用注释,eslint 看到这条注释就会乖乖绕道走开
    2. 全局设置
      1. YourProject/build/webpack.base.conf.js 中找到搜索 config.dev.useEslint, 将这行注释
        外链图片转存失败
      2. 同理,在YourProject/config/index.js 下,有一个useEslint参数,将其改为 false
        [外链图片转存失败在这里插入图片描述
      3. Yourproject/.eslintignore 文件中,在此文件中增加忽略的文件或文件夹[

    如何设置规则

    1. 如果你觉得不想关闭eslint,又不想被报错困扰,不如就学习一下eslint吧
    2. eslint 的规则包括两种,一种基本的一些配置,另一种是各种框架特有的配置

    vue, react, angular 等框架特有的配置

    1. Yourproject/.eslintrc.js 中,找到plugins这一项,填写合适的插件名
    2. 然后需要不同插件的官网查询详细的规则
    3. 推荐模式和基础模式

    eslint 基础的一些规则

    • eslint 规则官网
    • 在上图的位置,rules这一项里面填写即可,不需要的可以直接注释掉
    "off"或者0    //关闭规则关闭
    "warn"或者1    //在打开的规则作为警告(不影响退出代码)
    "error"或者2    //把规则作为一个错误(退出代码触发时为1)
    
    展开全文
  • 前端项目知识点总结

    千次阅读 2019-01-09 10:53:53
    前端总结 html 字体图标的引用 添加到项目 项目下载到本地 加font文件夹,将字体文件放进去 将css文件加入到link中 雪碧图 先用一个 span 标签 将span标签display:inline-block 设置图标的background-...
  • nginx 部署前端项目

    千次阅读 2019-06-03 13:17:30
    nginx如何部署打包成为dist的前端项目。读者须知: nginx如何安装与使用 PS docker 安装与使用 docker pull nginx docker run --restart=on-failure:20 -itd --name nginx -p 80:80 nginx:latest SEO nginx如何部署...
  • 前端项目优化

    千次阅读 2018-09-25 09:26:00
    经常会被问到这个问题,所以记录一下: ...2.合理使用浏览器缓存 3.使用压缩,尽可能的将外部的脚本、样式进行合并,多个合为一个,之前看的jquery.mini和普通版...5.CSS放在页面最上部,js放在页面最下面,js阻塞 HTML...
  • 使用nginx部署前端项目

    千次阅读 2019-04-26 22:38:08
    root <项目的路径>; index index.html index.htm; } 启动nginx查看运行情况 ps -ef | grep nginx 查看nginx运行的情况以及pid ./nginx -s quit 注意 以上操作需在nginx安装目录中,(可参考...
  • 一:把前端的资源打包放入到springboot项目中,打成jar包或者war包进行部署。 二:把前端资源放到NGINX代理服务器上,后端项目文件打成jar包或者war包启动。 具体采用哪种方式,看公司中已有的部署方式,在者就是...
  • nginx部署前端项目

    千次阅读 2020-05-12 17:31:32
    Jenkins 或是 您 手动把前端打包好的文件传到服务器的指定位置: 假设:/home/admin/dists/front-test 这路径后边要用到。 此处用到的是 安装nginx 1、 wget 下载地址 (官网传送门) 例如:wget ...
  • 前端项目结构整理

    千次阅读 2018-11-06 17:36:29
    my-project ├── .idea # 这个是编辑器生成的 ├── build # Webpack 配置文件放在这里 ├── config # Vue 基本配置文件放在这里 ├── node_modules # 第三方依赖 ├── src ...
  • 创建vue前端项目

    千次阅读 2018-08-08 00:18:13
    所以这个总结的目的呢就是为了总结自己的成长历程,提醒自己。 今年已经毕业一个月多了,就从去年的实习开始讲讲 17年6月份的时候我大三,当时也没有人找实习工作,很多一部分同学都选择了考研,剩下的人大...
  • 前端项目部署到云服务器

    千次阅读 2021-01-03 17:05:42
    前端开发完成的项目,不管是使用vue、react、或者是别的web项目,最终都是要部署到外网上,让用户可以通过域名来访问。这篇文章以一个 react 移动端的项目为例,讲怎样将自己本地的项目部署到阿里云服务器上。 文章...
  • 手把手教你VUE前端项目发布上线

    千次阅读 多人点赞 2020-06-25 10:00:16
    已经好的代码,有团队的需要拉取最新的代码(今天重点分享团队前端项目的发布过程) 软件:(包括但不限于)——如果工具都OK,将大大降低发布难度 Nginx:轻量级web服务器 Jenkins:持续集成开发工具 Tomcat...
  • docker nginx部署前端项目

    千次阅读 2020-05-30 18:26:02
    最近一直在搞前后端分类,一直在想前端的html页面应该用什么部署 想来想去,如果用tomcat好像有点浪费资源,作为...我们来利用docker来部署nginx项目 首先我们假设docker 安装成功,并且也获取了nginx镜像,如果
  • 前端项目中接口实现

    千次阅读 2019-05-23 06:13:24
    本篇文章基于 前后端完全分离,服务端只提供HTTP API,前端通过Ajax与服务端进行通信 为公司实习中遇到的后台管理系统中遇到的接口使用的总结。 1.从models文件夹中最基本的,state中需要定义引用的数据,并引入 ...
  • webpack打包前端项目

    万次阅读 2018-08-04 10:57:13
    (2)完成后,新建文件webpack.config.js,将其放在webxing目录下 (3)新建index.js为入口文件 require('../js/home.js'); require('../css/home.css'); (4)然后配置webpack.config.js: var ...
  • 前端项目资源文件使用cdn加速

    千次阅读 2018-11-26 08:59:18
    前端项目代码在上传到服务器以后 资源文件往往会很大 而使用的云服务一般带宽都会很小(带宽很贵) 所以资源往往需要放到cdn上面来加速 节约服务器的带宽 这里我们使用回源的方式来实现cdn加速 假设: oss(或...
  • 讲解增删改查等核心功能的前端实现,至此项目基本成型。
  • 前端项目实战(梅兰商城)

    万次阅读 2016-05-10 20:47:50
    前端项目步骤: 1.拿到美工设计图后,开始浏览页面布局,将页面简单划分出来 开发整站的两种方式: ①从上到下依次把每个盒子完 ②先把整站的布局给搞定,然后再把每个布局的盒子中的子元素补齐(模块化) 个人...
  • 前端项目部署到阿里云

    千次阅读 2019-01-21 18:48:00
    由于本人是个前端这里只介绍前端项目的部署(后台的部署见下一篇) 准备工作 下载两个软件Xshell和Xftp(也可以使用WinSCP;我使用的是windows系统) 购买阿里云,看需要选配置吧,系统一般选Ubuntu和CentOS;我选的是...
  • nginx部署vue前端项目的dist包

    千次阅读 2020-05-07 16:12:19
    以nginx作为容器部署vue的前端项目 首先几条必备的linux命令: 1、进入nginx目录:cd/usr/local/nginx/ 2、启动nginx:shsbin/nginx 3、停止nginx:sbin/nginx-s stop 4、重启nginx:sbin/nginx-s reload 5、...
  • 1.首先WEB-INF里的文件不能被外界访问,所以CSS,JS等文件不能放在此处,刚开始我把前端做出来的东西全部放在了WEB-INF下所以肯定不对。 2.通过问学长得知在html里面没有引进CSS的样式,好诡异的说,慧婷做好了给我...
  • vue.js前端项目部署到nginx服务器

    千次阅读 2018-06-22 12:03:04
    注: 本文选择了nginx做web服务器。因为在本文vue前端项目中,需要从接口获取数据,可是数据与vue前端项目是在同一ip地址但不同端口号,所以需要跨域读取数据。本文的跨域处理是使用了ng...
  • 用vue+webpack搭建的前端项目结构

    万次阅读 2016-09-30 18:40:05
    上个项目第一次用到vue+webpack,也是我第一次尝试自动化、模块化的开发方式,总的来说就是结构太烂,开发体验差,效率低,难维护。细数的罪状有如下几条 没有servies层,全部ajax接口都和逻辑混合在一起 只有公众...
  • 前端项目实战及原理

    千次阅读 2020-06-14 19:21:55
    使用微前端项目中主要是解决使用iframe引入第三方页面时遇到的框架受限,页面交互不统一等问题,项目中遇到的问题大概如下: iframe 内部路由跳转,不会影响到外部的路由地址,无法记住当前访问的页面地址,...
  • 前端时尚好用的图标项目-Font Awesome

    万次阅读 2020-09-30 14:55:21
    作为一个非专业的美工和前端的技术人员,在项目上有时需要用到一些图标,才能使前端看起来比较高大上,以前都是使用收集好的一些小图标,放在目录下面,通过手动添加图片标签来实现,但是这种方式比较繁琐,要收藏较...
  • 前端项目中使用Git Hooks

    千次阅读 2019-05-10 14:56:48
    前端项目中使用Git Hooks 具备基本工程素养的同学都会注重编码规范,而代码风格检查(Code Linting,简称 Lint)是保障代码规范一致性的重要手段。 使用 Lint 会有什么好处呢?在我看来至少具有如下 3 点: 更少...
  • 【转载】前端项目开发流程及技术选型

    万次阅读 多人点赞 2017-01-03 16:05:14
    据我所知,时至今日仍然有很多团队会把前端开发归类为产品或者设计岗位,虽然身份之争多少有些无谓,但我对这种偏见还是心存芥蒂,酝酿了许久,决定一个系列的文章,试着从工程的角度系统的介绍一下我对前端,尤其...
  • 前端项目性能优化记录~

    千次阅读 2021-04-06 09:49:49
    几个月前曾在某博客论坛上看到一篇令人称奇的所谓的前端性能优化的文章,感触很大 在此之前,一直把页面渲染的快慢,接口里面一个逻辑的优化处理(公司没有后端,用的是云函数,接口也是我来的),数据库里冗余字段的清除,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 114,109
精华内容 45,643
关键字:

自己写的前端项目可以放在那