Skip to content

webpack

webpack 基本概念

  1. entry 入口
    • 以某个文件为入口开始打包
    • 分类
      • 单入口 String

        只会输出一个文件

      • 多入口 Array / Object

        Array 只会输出一个文件

        Object 会输出多个文件 ==> 多页应用(MPA)

  2. output 输出
    • 打包后资源输出到哪里去
    • 输出的文件名叫什么
  3. loader 加载器
    • webpack 本身只能识别 json、js 模块,其他模块一旦加载就会报错.需要借助 loader 帮助 webpack 识别其它识别不了的模块
  4. plugins 插件
    • loader 功能有限,要想做功能更加强大的工作交给插件。比如在页面中自动引入打包生成的 js/css, 压缩 css, 拷贝文件等
  5. mode
    • 模式:开发环境(development)和生产环境(production)提供一系列默认配置, 用于简化配置

webpack 基本配置

  1. 处理 JS 文件
    • eslint-loader

    在 package.json 中配置 eslintConfig 来指示 eslint-loader 到底要干什么事enfore: 'pre' 优先执行

    • babel-loader

    在 webpack 配置中配置 babel 来指示 babel-loader 到底要干什么事 babel.config.js: 配置 webpack 的 preset 与 plugin

  2. 处理 Vue 文件
    • vue-loader
  3. 处理 JSX 文件
    • babel-loader
  4. 处理 CSS 文件
    • 开发环境:创建 style 标签插入样式
      • style-loader
      • css-loader
      • postcss-loader
      • less-loader / sass-loader / stylus-loader
    • 生产环境:提取单独 css 文件,将来通过 link 引入
      • MiniCssExtractPlugin.loader(还需要配置插件 new MiniCssExtractPlugin)
      • css-loader
      • postcss-loader
      • less-loader / sass-loader / stylus-loader
  5. 处理 HTML 文件
    • 目标: 自动引入打包生成的 js/css html-webpack-plugin
  6. 处理图片/字体/音视频文件
    • url-loader / file-loader limit: 10000 小于 10kb 一下的图片会被 base64 处理

webpack配置层面优化

  1. 优化打包构建速度
    • HMR 热模块替换
      • 为什么要用?
        • 默认情况下,一旦修改了代码,全部代码重新编译刷新,速度慢(全体刷新)
      • 有什么作用?
        • 只更新修改的模块,其他模块不变(局部更新)
      • 怎么使用?
        • devServer:
        • new webpack.HotModuleReplacementPlugin()
      • 注意:
        • 默认情况下只有样式文件有 HMR 功能(style-loader),JS 是没有的开启 JS 的 HMR 功能:
        • 手写 JS 代码 --> module.hot.accpet('模块路径', () => {})
        • 在 Vue 使用 --> vue-loader
        • 在 React 使用 --> react-hot-loader
    • 缓存
      • eslint 和 babel 两个任务处理 JS 文件,时间一般会比较长,为了让其重新构建速度更快, 可以使用缓存。
      • eslint --> cache: true
      • babel --> cacheDirectory: true
      • cache-loader 放置在要缓存 loader 的前面
      • 注意:一般只针对耗时长的任务:eslint-loader/babel-loader/vue-loader
    • oneOf
      • 作用:
        • 让模块只被一个 loader 处理,其他的就不看了(原本所有都会判断一下)
        • 能够提升打包速度
      • 注意:
        • eslint-loader: 处理 js, 需要先执行, 将其定义在 oneOf 的外面
        • babel-loader: 处理 js, 后执行, 将其定义在 oneOf 的内部
    • 多进程打包
      • 过去: happyPack 现在: thread-loader
      • 用法和 cache-loader 差不多,放在要使用 loader 前面
      • 作用:开启多进程处理前面的任务,提升打包速度
      • 注意:每个进程开启和通信都有开销,一般只针对耗时长的任务:babel-loader
  2. 兼容性处
    • js
      • babel-loader: presets: ['@babel/preset-env'] 问题就是只能编译/转换简单语法
      • @babel/polyfill: 做复杂语法(新的 APi)兼容,问题是体积太大了
      • core-js: 在@babel/preset-env 基础上,增加了 useBuiltIns: 'usage'来实现按需打包
      • eslint-loader package.json 中配置 eslintConfig 来指示 eslint-loader 到底要干什么事enfore: 'pre' 优先执行
    • css
      • postcss-loader
      • 内部使用 autoprefixer 插件, 给 w3c 样式自动添加厂商前缀
      • package.json 中指定 browserslist 来指示 postcss-loader 兼容性做到什么程度
      • 开发环境
        • style-loader
        • css-loader
        • postcss-loader
        • less-loader / sass-loader / stylus-loader
      • 生产环境
        • MiniCssExtractPlugin.loader(还需要配置插件 new MiniCssExtractPlugin)
        • css-loader
        • postcss-loader
        • less-loader / sass-loader / stylus-loader
    • vue vue-loader
    • html html-webpack-plugin 自动引入打包生成的 js/css
    • 图片/字体/音视频文件 url-loader / file-loader limit: 10000 小于 10kb 一下的图片会被 base64 处理
  3. 拆分打包与压缩
    • 作用:
      • 抽取公共代码
      • 拆分多个文件,减少单个文件体积(避免单次请求时间过长)
    • 配置:
      • 多入口+ optimization
        • 将node_modules抽取成单独模块
        • 将多入口的公共模块也抽取成单独模块
      • 单入口+optimization+import
        • 将node_modules抽取成单独模块
        • 动态导入语法import就能将某些文件抽取成单独模块
      • import()动态引入模块
      • 原生Js:在需要的回调函数中动态加载模块,import(模块).then()
      • Vue:()=>import('./Foo.vue'),实现路由组件懒加载
  4. 资源预加载(prefetch)
    • 作用
      • 让资源提前加载
    • 区别:
      • preload 让当前页面的要使用资源加载(延后加载)
      • prefetch 让后面要使用资源提前加载(当前不需要使用)
    • 使用:
      • import(/* webpackPrefetch: true */'./xxx')
      • import(/* webpackPreload: true */'./xxx') // 没有效果
      • 问题:兼容性较差
    • 使用chrome团队提供的一个工具包:preload-webpack-plugin
      • npm i-D preload-webpack-plugin@next //必须是最新的下一个版本
      • 对异步模块包使用:prefetch
      • 对同步模块包使用:preload
  5. 生产环境时不生成 SourceMap
    • productionSourceMap: false 减少打包文件
  6. 文件名 hash 化=>利用浏览器缓存
    • 对打包文件名用上 contenthash ==> 某个 bundle 对应的模块文件内容发生改变文件名才会变化 ===> 利用浏览器缓存
    • hash、chunkhash、contenthash,首先生成效率越来越低,成本越来越高,影响范围越来越小,精度越来越细。
    • hash是一整个项目,一次打包,只有一个hash值,是项目级的
    • chunhash是从入口entry出发,到它的依赖,以及依赖的依赖,依赖的依赖的依赖,等等,一直下去,所打包构成的代码块(模块的集合)叫做一个chunk,也就是说,入口文件和它的依赖的模块构成的一个代码块,被称为一个chunk。
    • contenthash是哈希只跟内容有关系,内容不变,哈希值不变。与chunkhash的区别可以举上面contenthash的例子,同时可以说明contenthash跟内容有关,但是chunkhash会考虑很多因素,比如模块路径、模块名称、模块大小、模块id等等。
  7. 代码 Tree Shaking
    • 效果: 打包时'摇掉'模块中没有被使用的代码 条件: 必须是 ES6 模块化导出且进行代码压缩时
    • 必须使用 ES6 模块化(需要禁止@babel/preset-env 转换 ES6 模块化语法 modules: false)
    • 开启 webpack 的生产模式(内部启用 TerserPlugin,用来压缩 JS 代码的插件,tree shaking 功能就是这个插件完成的)
    • 在 package.json 配置 sideEffects 来指定哪些文件需要进行 tree shaking

说说如何借助webpack来优化前端性能?

> webpack是一个模块打包工具,可以使用webpack管理模块,并分析模块间的依赖关系最终编译输出模块为html、JavaScript和css以及各种静态文件,让开发更加高效

通过webpack优化前端的手段有:

> JS代码压缩、CSS代码压缩、Html文件代码压缩、文件大小压缩、图片压缩、Tree Shaking、代码分离、内联 chunk

nginx

nginx基本功能

* 作为服务器运行前端项目(gshop-client / gshop-admin)
* 作为代理服务器, 转发前端项目的请求到后台接口
* 配置api代理
bash
    server {
        listen 8081; 
        server_name localhost;
        # 处理所有与后面不匹配的请求
        location / {
            root D:\work\online\gshop-client; # 项目资源的根目录
            index index.html index.htm; # 首页页面
            # try_files $uri $uri/ /index.html; # 所有 404 的请求返回 index 页面
        }
        # 处理所有/api 开头的请求
        # 转发到后台接口地址
        # 转发时不要去掉/api 
        location /api {
            proxy_pass http://39.98.123.211;
        }
    }
    server {
        listen 8082; 
        server_name localhost;
        location / {
            root D:\work\online\gshop-admin;
            index index.html index.htm;
        }
        # 所有/api 开头的请求都转发到后台接口地址
        # 转发时去掉/prod-api
        location /prod-api/ {
            proxy_pass http://39.98.123.211/;
        }
    }

nginx解决404

bash
    location / {
    # 解决 history 模式, 浏览器刷新 404 问题
    try_files $uri $uri/ /index.html; # 所有 404 的请求返回 index 页面
    }

token存在sessionstorage还是loaclstorage

token:验证身份的令牌,一般就是用户通过账号密码登录后,服务端把这些凭证通过加君

  • 存loaclstorage里,后期每次请求接口都需要把它当作一个字段传给后台
  • 存cookie中,会白动发送,缺点就是不能跨域

如果存在localstorage中,容易被xss攻击,但是如果做好了对应的措施,那么是利大于 如果存在cookie中会有CSRF攻击

token的登录流程

  1. 客户端用账号密码请求登录
  2. 服务端收到请求后,需要去验证账号密码
  3. 验证成功之后,服务端会签发一个token,把这 个token发送给客户端
  4. 容户端收到token后保存起来,可以放在cookie也可以是localstorage
  5. 客户端每次向服务端发送请求资源的时候,都需要携带这 个token
  6. 服务端收到请求,接着去验证客户端里的token,验证成功才会返回客户端请求的数据

了解过JWT吗

JSONWebToken 通过了JSON形式作为在web应用中的令牌,可以在各方之间安全的把信息作为JSON对象传输(信息传输、授杈)

JWT的认证流程

  1. 前端把账号密码发送给后端的接口
  2. 后端核对账号密码成功后,把用户id等其他信息作为JWT负载,把它和头部分别进base64编码拼接后签名,形成一个JWT (token) .
  3. 前端每次请求时都会把JWT放在HTTP请求头的Authorization字段内
  4. 后端检查是否存在,如果存在就验证JVT的有效性(签名是否正确,token是否过期)
  5. 验证通过后后端使用JWT中包含的用户信总进行其他的操作,井返回对应结果

处理无感登陆

  1. 在相应其中拦截,判街token返回过期后,调用刷新token的接口
  2. 后端返回过期时间,前端判断token的过期时间,去调用刷新token的按口
  3. 写定时器,定时刷新token接口

流程:

  1. 登录成功后保存token 和 refresh_token
  2. 在响应拦截器中对401状态码引入刷新token的api方法调用
  3. 替换保存本地新的token
  4. 把错误对象里的token替换
  5. 再次发送未完成的请求
  6. 如果refresh_token期了,判新是否过期,过期了就清楚所有token重新登录

vue和react对比

  • 相同点
    • 都有组件化思想
    • 都支持服务器端渲染
    • 都有Virtual DOM(虚拟dom)
    • 数据驱动视图
    • 都有支持native的方案:Vue的weex、React的React native
    • 都有自己的构建工具:Vue的vue-cli、React的Create React App
  • 不同点
    • 数据流向的不同。react从诞生开始就推崇单向数据流,而Vue是双向数据流
    • 数据变化的实现原理不同。react使用的是不可变数据,而Vue使用的是可变的数据
    • 组件化通信的不同。react中我们通过使用回调函数来进行通信的,而Vue中子组件向父组件传递消息有两种方式:事件和回调函数
    • diff算法不同。react主要使用diff队列保存需要更新哪些DOM,得到patch树,再统一操作批量更新DOM。Vue 使用双向指针,边对比,边更新DOM

Released under the MIT License.