Webpack入坑笔记(二) 小图片优化,引入CSS,使用ES6

今天我要进一步深入的了解webpack的各种功能,webpack有着无数插件可以为项目提供各种支持,其中一部分对项目文件进行预处理的插件叫做loader(预处理器),比较常用的有:

  1. css预编译,less或sass预编译 css-loader,style-loader,less-loader 把css预编译并通过style标签嵌入到页面
  2. 小图片优化生成base64码 url-loader 减少请求数
  3. 使用Jquery等类库
  4. 支持ES6语法 babel-loader 装逼(使用新特性提供开发效率)
  5. 代码压缩 节约流量

我们分别来尝试一下以上提到的功能

css预编译

在我们的app目录下新建一个文件夹css /app/css/ 用来存放我们的CSS文件,新建一个main.css文件

main.css

h1{
  color:blue;
}

安装预处理器 style-loader,css-loader

npm install style-loader css-loader --save-dev //一行命令要安装多个插件,可以用空格隔开

安装完成后,配置webpack.config,注意以下几点:

  1. 所有的预处理器的处理顺序是从后往前(从右到左)
  2. 在webpack 2.0版本后,预处理器不能省略-loader,例如:'style-loader'不能简写为'style'
...
module:{
loaders:[{
test: /\.css$/,
loaders:['style-loader','css-loader'],
include:APP_PATH
}]
}
...

不要忘了在index.js引用我们的css文件

require('./css/main.css')

然后执行npm start,你应该能看到蓝色的hello world字样了

使用Less

让我们接着上一步,如果我要使用sass或者less,应该怎么办呢,答案也非常简单,只需安装less预处理器,并在配置文件里配置对less的预处理即可

npm installless-loader --save-dev

webpack.config配置

module:[
  ...
  {
    test:/\.less$/,
    loader:['style-loader','css-loader','less-loader'] //是不是非常简单,只需要在预处理程序上加一道即可
  },
  ...
]

在/app/下新建目录 /app/less,新建文件main.less

@base: red;
h1 {
    color: @base;
};

h2 {
  color:blue;
}

在index.js中修改引用

require('./less/main.less');

然后 npm start,编译成功!又看到了熟悉的hello world,只不过这次第一行变成了红色,第二行变成了蓝色

小图片优化

首先我们在我们的目录下新建一个文件夹 /app/images/ 用来存放我们的图片,这里我选用了2张猫咪的图片,一张有270kb,另一张则是21.6kb.我们的目标是当浏览器加载40KB以下的图片时,把图片转化成dataurl,这样可以减少请求数,提高网页加载的速度.先看下没有预处理器下,图片的处理情况

我们的文件目录结构:

我们在less中为h1,h2增加背景图片

@base: red;
@height: 300px;

h1 {
    color: @base;
    background: url('../images/p1.jpg') no-repeat;
    background-size:;
    height: @height;
};

h2 {
    color:blue;
    background: url('../images/p2.jpeg') no-repeat;
    background-size: contain;
    height: @height;
}

我们在html中用标签也添加一张图片,这里应该通过JS来生成到html中,我们添加一个组件images.js

function printIMG(){
  var div=document.createElement('div');
  div.innerHTML='Here is a picture from js<br>'
  div.innerHTML+='<img src="/app/images/p1.JPG">';
  return div;
}
module.exports=printIMG;

在index.js中引用它,注意我们这里还有个同名的images目录,但webpack自动识别了require中的images.js

require('./less/main.less');
var sub=require('./sub');
var img=require('./images');
var app=document.createElement('div');
app.innerHTML='<h1>Hello World 1111111</h1>';
app.appendChild(sub());
app.appendChild(img());
document.body.appendChild(app);

运行webpack后,我们看到页面上多了3张图片,查看HTML和CSS后,发现现在所有图片都是直接引用的url

然而我们的需求是要把40KB以下的图片全部转化成base64的形式,现在我们使用url-loader来做这件事,
首先,安装插件 url-loader

npm install url-loader --save-dev

然后在webpack.config中配置

...
module: {
  loaders: [
    ...
    {
      test: /\.(png|jpg|jpeg)$/, //可以定义多种格式
      loader: 'url-loader?limit=40000?name=images/[name].[ext]' //在预处理器后可以通过?增加参数,这里?limit=40000的意思是把所有40000b以下的图片转化成base64格式
    },
    ...
  ]
},
...

然后让我们再运行下看看结果

这个时候我们发现background里的图片已经变成base64格式了(见框1),但框2中的img标签里同样的图片却没有转化.
这是由于url-loader不支持打包JS里的src导致的,为了打包时候不丢失图片,我们可以通过require的方式引用图片,这样就可以通过url-loader来打包了,把images.js改一下:

var imgUrl= require('./images/p1.jpg');//注意!后缀名必须是小写,大写会报错
var imgTemp='<img src="'+imgUrl+'" />';
function printIMG(){
  var div=document.createElement('div');
  div.innerHTML='Here is a picture from j11111111111s<br>'
  div.innerHTML+=imgTemp;
  return div;
}
module.exports=printIMG;

使用Jquery等类库

如果要在项目中使用各种类库,步骤也是和安装插件一样的
首先

npm install jquery --save

然后在需要使用jquery的页面上require一下

var $=require('jquery');
...
$('body').append('<p>Jquery is work now</p>');

这里笔者产生了一个问题,为什么require('jquery')就能直接找到node_modules下的jquery文件呢
这是因为如果require中的内容如果不包含'/'、'./'或'../'开头的话,默认会先寻找node_modules目录下的相关文件,这里的require('jquery')等价于 require('./node_modules/jquery')
参考:阮大神的文章

当 Node 遇到 require(X) 时,按下面的顺序处理。
(1)如果 X 是内置模块(比如 require('http'))
  a. 返回该模块。
  b. 不再继续执行。
(2)如果 X 以 "./" 或者 "/" 或者 "../" 开头
  a. 根据 X 所在的父模块,确定 X 的绝对路径。
  b. 将 X 当成文件,依次查找下面文件,只要其中有一个存在,就返回该文件,不再继续执行。

X
X.js
X.json
X.node

c. 将 X 当成目录,依次查找下面文件,只要其中有一个存在,就返回该文件,不再继续执行。

X/package.json(main字段)
X/index.js
X/index.json
X/index.node

(3)如果 X 不带路径
  a. 根据 X 所在的父模块,确定 X 可能的安装目录。
  b. 依次在每个目录中,将 X 当成文件名或目录名加载。
(4) 抛出 "not found"

运行后,可以看到,Jquery的代码已经成功输出了!

支持ES6语法 babel-loader

如果想要使用es6,我们需要安装babel编译器,他可以把ES6语法解析成浏览器能兼容的JavaScript,我们还要安装适用于babel的ES2015语法转换器(babel-preset-es2015)

npm install babel-loader babel-preset-es2015 --save-dev

在webpack.config中配置

...
{
  test: /\.jsx?$/,
  loader: 'babel-loader',
  exclude: /(node_modules|bower_components)/,
  query: {
    presets: ['es2015'] //表示使用es2015语法转换器
  }
},
...

关于babel-loader的设置可以参考 这里

然后我们修改下原来的js文件,可以使用ES6语法了

sub.js

export default function(){
  var h2=document.createElement('h2');
  h2.innerHTML='Hello World h2';
  return h2;
}

images.js

import imgUrl from './images/p1.jpg';
let imgTemp='<img src="'+imgUrl+'" />';
export default function(){
  let div=document.createElement('div');
  div.innerHTML='Here is a picture from j11111111111s<br>'
  div.innerHTML+=imgTemp;
  return div;
}

index.js

//ES6风格
import './less/main.less';
import sub from './sub';
import images from './images'
import $ from 'jquery';
import moment from 'moment';

let app = document.createElement('div');
const myPromise = new Promise(function(resolve,reject){
  setTimeout(function(){
    console.log('执行完成');
    resolve('101');
  },5000);
});
myPromise.then((value)=>{
  $('body').append('<p>promise result is ' + value + ' now is' + moment().format('YYYY-MM-DD hh:mm:sss')+'</p>');
});
app.innerHTML='<h1>Hello world H1</h1>';
document.body.appendChild(app);
app.appendChild(sub());
app.appendChild(images());

运行一下,依然是我们熟悉的hello world,并且promise的结果也print出来了.

代码压缩

现在我们对webpack基本的功能都有一定的了解了,最后生成项目的时候,页面里的js和css都是未经过压缩的,并且我们所引用到的类库都被打包到了bundle.js里,导致这个JS文件非常大,在实际生成项目中,我们通常只上线自己所写的JS代码,所有的类库都会缓存到CDN上来分流,这个需求在webpack中也是可以实现的.首先我们来拆分项目中的Jquery和Moment 这2个库

修改webpack.config,添加externals属性可以在webpack打包时排除在externals下的依赖包
例如:我们排除jquery和moment,这样在webpack打包时就不会把这2个库打包到bundle.js下了

...
externals:[
   {'jquery':'jQuery','moment':'moment'},
],
...

我们可以在template模板中对未打包的文件进行设置,比如设置CDN,我这里由于没有CDN,就用node_modules代替了

<!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>Document</title>
</head>
<body>
hello this is from template
<script src="../node_modules/jquery/dist/jquery.min.js" charset="utf-8"></script>
<script src="../node_modules/moment/min/moment.min.js" charset="utf-8"></script>

</body>
</html>

另一种压缩是对js本身进行的压缩 可以通过webpack自带的插件进行

...
plugins:[
  new webpack.optimize.UglifyJsPlugin({//压缩JS
    compress:{
      warnings:false
    }
  }),
]
...

运行weback 打包后的文件更小了

发布了35 篇原创文章 · 获赞 9 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/qq_31061615/article/details/80743239
今日推荐