构建多页面应用——静态资源的处理

在之前的系列文章中,我已经介绍了如何用webpack实现多页面应用的js,html,css的处理。今天就主要介绍如何处理静态资源,在web开发中最常见的静态资源就是图片。

图片的引用方式

而因为在web中,图片有两种主要的引入方式,第一种是<img src="...">,第二种是backgorund-image: url(...)。前者在html中使用,后者在css中使用。

web开发中的图片处理

图片常见的类型有jp(e)g,png,gif,包括现在普遍使用的svg以及webp。svg作为矢量图形,有一定的使用场景,而webp作为未来web开发的趋势,有一定的使用场景,比如:爱奇艺中的轮播图(carousel)中就是用webp,但其他的见到的不多。

现在,web开发中使用最多的还是jpg和png,处理他们,在构建工具中使用url-loaderfile-loader就好了,其中file-loader负责图片的拷贝和输出,并会给图片名添加一个hash值。

说到这里,很多人会想到字体图标。以前处理web页面中的图标(icon),使用图片来处理,这样会带来一个性能问题就是http请求的增多,这样会造成服务器的负载压力,同时会带来用户体验的问题,因为会出现页面的局部空白和页面重绘的问题,当然一种解决方案使雪碧图(sprite),但是如果图片过大怎么解决,如何对图片进行分解(大变小的问题),图片的拼接比较困难,最要命的是在引用雪碧图时要进行计算,除此之外就是如何对雪碧图的组成图片进行自定义的删减,而使用字体图标这些问题,都会得到一定程度的解决,当然在构建工具中可以使用webpack-spritesmith这个插件来处理组成雪碧图的图片。

当然,有些特殊的情况,需要使用base64,这里使用url-loader即可。

将图片处理为base64有使用场景,将图片转换为雪碧图亦有使用场景,单独的图片处理也有使用场景(这些使用场景的图片大小从左到右依次增大)。

这些场景在一个web项目中都会涉及到。

虽然使用字体图标可以替代雪碧图,因为字体图标有更小的尺寸,更自由的操作手法(如:图标颜色的自定义),但是一个DIY的web项目还是有些图标还是需要雪碧图。

但是,这里有一个问题,如何在一个项目中同时使用base64,雪碧图,字体图标,单独的图片。

在构建中如何使用多种图片处理方式

在构建多页面应用中,如何解决呢?

字体图标

处理字体图标很简单,如:iconfont(阿里巴巴字体图标库),就像引用css那么简单。

base64

base64的处理,使用url-loader

雪碧图

雪碧图的处理,可使用webpack-spritesmith这个插件

单独的图片

使用file-loader,它负责拷贝url-loader的处理结果,并输出。

上面就是我们常见的图片处理,如果要处理svg可以参考svg-url-loader,如果要处理webp可以参考webp-loader

如何对图片进行优化

对图片进行优化,会带来良好的用户体验。

熟悉图片优化的都知道渐进式(progressive),可参考nuwen.net

jp(e)g可以进行连续性处理,这样可保证图片数据请求回来多少,就渲染多少,是自上而下的渲染,也是有模糊到清晰的状态。

png可以进行交叉处理,这样也可保证图片数据请求回来多少,就渲染多少,它是整体的显示,而且是又模糊状态到清晰的状态。

gif图片一般使用小图,如果是大图会记号浏览器性能,还不如使用视频,或者用css动画来代替。我个人整理了一个css 动画集,有需要的可以看一下。

在构建多页面应用中,会使用到image-webpack-loader来做优化处理。

其中,配置项options中的mozjpeg 处理jp(e)g图片,pngquant处理png图片,gifsicle处理gif图片,webp处理webp图片。

多页面应用中的图片处理

首先,看一下多页面应用中的目录结构图:


./src
│  aboutUs.js
│  contactUs.js
│  css.js
│  index.js
│  recruitment.js
│
├─assets
│  │  favicon.jpg
│  │
│  ├─css
│  │  │  index.scss
│  │  │
│  │  ├─commons
│  │  │  ├─container
│  │  │  │      index.scss
│  │  │  │
│  │  │  ├─footer
│  │  │  │      index.scss
│  │  │  │
│  │  │  └─header
│  │  │          index.scss
│  │  │
│  │  ├─productus
│  │  │      index.scss
│  │  │      productus-sprite.scss
│  │  │
│  │  └─utils
│  │          btn.scss
│  │          form.scss
│  │          inital.scss
│  │          list.scss
│  │          modeal.scss
│  │          normalize.scss
│  │          pagination.scss
│  │          popover.scss
│  │          table.scss
│  │          text.scss
│  │          tooltip.scss
│  │
│  └─imgs
│      ├─base64
│      │      fe.jpg
│      │
│      ├─other
│      │      float.jpg
│      │      productus-sprite.png
│      │
│      └─sprites
│          └─productus
│                  product-us_01.png
│                  product-us_02.png
│                  product-us_03.png
│                  product-us_04.png
│                  product-us_05.png
│                  product-us_06.png
│                  product-us_07.png
│                  product-us_08.png
│                  product-us_09.png
│                  product-us_10.png
│                  product-us_11.png
│                  product-us_12.png
│
├─pages
│  │  recruitment.pug
│  │  template.pug
│  │
│  └─components
│      ├─commons
│      │  ├─container
│      │  │      index.pug
│      │  │
│      │  ├─footer
│      │  │      index.pug
│      │  │
│      │  └─header
│      │          index.pug
│      │
│      └─productus
│              index.pug
│
└─utils
        load.js

跟以前的实例代码相比,这次的文件目录结构变化较大,这里将要处理的所有文件模块都放在了src目录下。

可能有人会问,为什么要要将目录分的这么细,下面我就说一下为什么这么分。

  • aboutUs.js, contactUs.js, index.js, recruitment.js是四个路由页面,要用到的js代码,css.js处理各个路由页面公用的css代码;
  • 静态资源目录(assets)下,存放web项目常用的静态资源;
  • 静态资源目录下的css目录统一存放整个web项目所用到的css样式。其中commons存放公用的css模块,每个公用模块有创建一个目录存放该公用模块可以使用到的css模块(提醒,不要分的过于细),而其他的如productus存放产品模块代码,根据开发的需要可以创建其他的模块目录,目录结构类似于commons中的header模块,其中utils放置自己总结的工具模块代码,如tableform等。然后,指定style-loader,css-loader等样式相关的loader处理css样式文件,这样可以减少遍历,缩短构建时间。
  • 静态资源目录下的imgs目录,用来存放整个项目中,用到的图片。在这里,分为base64spriteohter等,为什么要这样分?如果分的话file-loader这个webapck的loader会复制并导出imgs目下所有的图片,者在构建中并不是我们需要的,这样会增加构建的时间。如果让url-loader处理base64目录下的图片,file-loader处理ohter目录下的图片,webpack-spritesmith处理sprite目录下的图片,并将生成的图片放到ohter目录下,用file-loader进行二次处理。这样做,webpack处理更精确,可以减少不必要的遍历,极大地减少构建的时间,同样方便对图片的管理,特别是对于需要改变sprite的图片的管理。
  • imgs目录下创建base64目录,sprite目录,使用file-loader指定处理ohter目录,是为了避免file-loader将所有的图片都拷贝一份并导出到dist输出目录中,因为与base64相关的文件已经在css样式文件中了,再拷贝一份,已经没有意义,而sprite相关的文件会被webpack-spritesmith插件先处理生成一个文件,所以再拷贝它们也没有意义,还会让构建速度更慢。
  • page目录下,放置所有的html代码块(这里使用pug编译器生成相应的html代码块),它的目录分类和css相类似,它们是一一对应的关系。

注意:iamge-webpack-loader,要先对所有的图片进行优化处理,然后再用其他loader处理。loader的执行顺序,如果你是style-loader!css-loader!sass-loader"使用,它是从右到左方向先后执行,如果你是在配置文件中的rules: [...]数组中,它也是从右到左的方向执行,如果你将所有的loader规则有回车符号隔开,那么它就是自下而上的执行。

一类特殊的图片引用

针对<img src="...">的图片使用,ul-loader是不会处理html中的img引用,现在处理这样情况的loader或插件,也并没有一个比较出名的。现在通用的做法就是将图片拷贝一份到生成目录中,copy-webpack-plugin。参考配置代码如下:


new CopyWebpackPlugin([
  {
  from: path.resolve(__dirname, ‘assets/imgs/other/‘),
  to: path.resolve(__dirname, ‘dist/assets/imgs/other/‘),
  ignore: [‘.*‘]
  }
]),

但这样,会带来另一个问题就是图片的优化问题,如何使用 image-webpack-loader?本来的目的是对项目中使用到的所有的图片进行优化,而现在只能对base64sprite目录下的图片进行优化处理。不过,不要慌,可以通过创建一个新的npm脚本命令(本是里使用的是npm run img)来对图片进行压缩处理,新建了一个目录static用来保存优化前的图片,ohter用来保存优化后的图片。

首先,需要安装imagemin, imagemin-mozjpeg, imagemin-optipng, imagemin-gifsicle :


yarn add imagemin imagemin-mozjpeg imagemin-optipng imagemin-gifsicle --dev

然后,在项目的根目录添加一个优化图片的文件optzing-img.js,代码如下:


const path = require(‘path‘)
const imagemin = require(‘imagemin‘);
const imageminMozjpeg = require(‘imagemin-mozjpeg‘);
const imageminOptipng = require(‘imagemin-optipng‘);
const imageminGifsicle = require(‘imagemin-gifsicle‘);

(async () =&gt; {
    await imagemin(
    [
      path.resolve(__dirname, ‘src/assets/imgs/static/*.jpg‘),
      path.resolve(__dirname, ‘src/assets/imgs/static/*.png‘),
      path.resolve(__dirname, ‘src/assets/imgs/static/*.gif‘)
    ],
    path.resolve(__dirname, ‘src/assets/imgs/other/‘),
    {
      use: [
        imageminMozjpeg(),
        imageminOptipng(),
        imageminGifsicle()
      ]
    }
  );

    console.log(‘图片优化完成!‘);
})();

最后,在package.json文件中添加如下的npm命令:


...
"scripts": {
    ...
    "img": "node optzing-img.js"
  },
...

在控制输入npm run img,然后按下回车键就可以得到你所需要的。

注:既然重新定义了图片优化的npm脚本命令,那么,是否需要去掉之前在webpack.config.js中的image-webpakc-loader,当然不需要。主要有两个原因,一个是sprite雪碧图它是用几张小图片合成了一张大图片,这张合成的图片还需要优化;另一个是因为本项目对于存放图片的目录进行了细化。

字体

在web开发中,自定义的字体也是比较常见的,在webpack中它的处理和图片类似,都是使用的 url-loaderfile-loader。参考代码如下:


...
{
  include: path.resolve(__dirname, ‘assets/fonts/‘),
  test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
  use: [{
    loader: ‘url-loader‘,
    options: {
      limit: 10000,
      name:  isDev ? ‘[name].[ext]‘ : ‘[name].[hash].[ext]‘,
      outputPath: ‘assets/fonts/‘
    }
  }]
},
...

新创建了一个fonts目录又来存放项目开发过程中使用的字体。

源代码

webpack4.x multi-page

此后,webpack构建多页面应用系列文章的源代码,都在这个github项目中,webpack3.x multi-page不再维护。

构建多页面应用系列文章

来源:https://segmentfault.com/a/1190000017579965

原文地址:https://www.cnblogs.com/qixidi/p/10224698.html

时间: 2024-08-01 03:07:30

构建多页面应用——静态资源的处理的相关文章

用node.js express设置路径后 子路径下的页面访问静态资源路径出问题

在routes/news_mian.js 设置了访问news_main.html 的路径 '/',通知设置一个访问news-page.html的子路径'/newspage'子路径.但是在访问loaclhost:3000/news/newspage时静态资源路径前多了一个/news导致不能找到静态资源 app.js var express=require('express'); var app=express(); var path=require('path'); var http=requir

转转hybrid app web静态资源离线系统实践

一.前言 目前的转转app是一个典型的hybrid app,采用的是业内主流的做法: 客户端内有大量业务页面使用webview内加载h5页面承载. 其优点是显而易见的,即:web页面上线频度满足快速迭代的业务需求,不受客户端审核和发版的时间限制,也可以将各个业务线的开发工作分摊到各个业务的fe团队上,使得个业务线可以并行开发. 而缺点,则不言而喻的在于客户端内webview加载h5页面,准确来说是web应用的性能和体验,是肯定不及客户端的.本篇文章中,笔者将会梳理立足于本团队内,根据团队的特点和

关于Spring boot2.0+配置拦截器拦截静态资源的问题

第一次遇到这个问题的时候,简直是一脸蒙逼,写了一个拦截器以后,静态资源就不能访问了,到处查找才知道是版本问题 解决办法: 第一步:定义一个类实现 实现WebMvcConfigurer的类中拦截器中添加放行资源处添加静态资源文件路径: @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(sessionInterceptor).addPathPatterns("/&

nodejs 构建本地web测试服务器 以及 解决访问静态资源的问题!

直接打开html文件,是以file:///方式打开的,这种方式很多时候会遇到跨域的问题,因此我们一般会搭建一个简易的本地服务器,来运行测试页面. 一.构建静态服务器 1.使用express模块 建立个js文件,命名server,内容代码如下: 1 var express = require('express'); 2 var app = express(); 3 var path = require('path'); 4 5 //指定静态资源访问目录 6 app.use(express.stat

Spring MVC Restful构建中静态资源访问问题

在构建Spring MVC Restful风格的应用时,由于在web.xml中: <span style="font-family:Microsoft YaHei;font-size:18px;"><servlet> <servlet-name>story</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</se

页面性能优化:preload预加载静态资源

本文主要介绍preload的使用,以及与prefetch的区别.然后会聊聊浏览器的加载优先级. preload 提供了一种声明式的命令,让浏览器提前加载指定资源(加载后并不执行),在需要执行的时候再执行.提供的好处主要是 将加载和执行分离开,可不阻塞渲染和 document 的 onload 事件 提前加载指定资源,不再出现依赖的font字体隔了一段时间才刷出 如何使用 preload 使用 link 标签创建 <!-- 使用 link 标签静态标记需要预加载的资源 --><link r

Thymeleaf静态资源引入方式及公共页面代码抽取

静态资源引入 Thymeleaf模板引擎url问题,要用如下的方式写,确保在任何情况下都能访问到 <!-- Bootstrap core CSS --> <link href="bootstrap/dist/css/bootstrap.min.css" rel="stylesheet"> <!-- 引用webjars的方式引入静态资源 --> <link th:href="@{/webjars/bootstrap/

nginx缓存静态资源,只需几个配置提升10倍页面加载速度

nginx缓存静态资源,只需几个配置提升10倍页面加载速度 首先我们看图说话 这是在没有缓存的情况下,这个页面发送了很多静态资源的请求: 1.png 可以看到,静态资源占用了整个页面加载用时的90%以上,而且这个静态资源还是已经在我使用了nginx配置压缩以后的大小,如果没有对这些静态资源压缩的话,那么静态资源加载应该会占用这个页面展示99%以上的时间.听起来是不是已经被吓到了,但是数据已经摆在这里了,这可不是危言耸听. 然后再看看使用了nginx缓存之后的效果图: 2.png 看到没有,朋友们

spring boot 静态资源的映射规则 (3) 欢迎页面映射

欢迎 页面映射   会从 4个静态资源目录 + 根路径 / 中 查找 index.html 页面 会在 静态资源目录下 与 根路径查找 (按该顺序) index.html页面: 收到 "/**" 请求映射 访问 localhost:8080/ 会在上面5个目录中查找 index.html 页面(因为/也属于 /** ) 原文地址:https://www.cnblogs.com/guangzhou11/p/12388954.html