五.webpack中使用loader和plugin

1.Loaders

1.1简介

Loaders是Webpack最重要的功能之一,他也是Webpack如此盛行的原因。通过使用不同的Loader,Webpack可以的脚本和工具,从而对不同的文件格式进行特定处理。

Webpack的API:
Webpack使用loader
http://webpack.github.io/docs/using-loaders.html
webpack的API中使用module-loader(包括include,exclude等)
http://webpack.github.io/docs/configuration.html#module-loaders

简单的举几个Loaders使用例子:

  1. 可以把SASS文件的写法转换成CSS,而不在使用其他转换工具。
  2. 可以把ES6或者ES7的代码,转换成大多浏览器兼容的JS代码。
  3. 可以把React中的JSX转换成JavaScript代码。

注意:所有的Loaders都需要在npm中单独进行安装,并在webpack.config.js里进行配置。下面我们对Loaders的配置型简单梳理一下。

  • test:用于匹配处理文件的扩展名的表达式,这个选项是必须进行配置的;
  • use:loader名称,就是你要使用模块的名称,这个选项也必须进行配置,否则报错;
  • include/exclude:手动添加必须处理的文件(文件夹)或屏蔽不需要处理的文件(文件夹)(可选);
  • query:为loaders提供额外的设置选项(可选)。

1.2loader的三种写法:

第一种写法:直接用use。

 module:{
        rules:[
            {
                test:/\.css$/,
                use:['style-loader','css-loader']
            }
        ]
    },

第二种写法:把use换成loader

module:{
        rules:[
            {
                test:/\.css$/,
                loader:['style-loader','css-loader']
            }
        ]
    },

第三种写法:用use+loader的写法:

 module:{
        rules:[
            {
                test:/\.css$/,
                use: [
                    {
                        loader: "style-loader"
                    }, {
                        loader: "css-loader"
                    }
                ]
            }
        ]
    }

2.CSS文件打包

在我的上一篇的博客中已经介绍了生成html文件,这里就不再多说了。
node的path的用法
http://nodejs.cn/api/path.html#path_path_resolve_paths

2.1 style-loader和css-laoder

这里我们需要两个解析用的loader,分别是style-loader和css-loader。

style-loader:
它是用来处理css文件中的url()等,npm中的网址:https://www.npmjs.com/package/style-loader

    npm install style-loader --save-dev

css-loader:
它是用来将css插入到页面的style标签。npm中的网址:https://www.npmjs.com/package/css-loader

    npm install --save-dev css-loader

2.2 loaders配置:

首先我们的目录:
这里写图片描述
style.css

body {
    background: red;
}

entry.js

import css from './style.css'
console.log('pp');

webpack.config.js

const path = require('path');
const htmlPlugin= require('html-webpack-plugin');

module.exports = {
    entry: {
        entry: __dirname + '/src/entry.js'
    },
    output: {
        path: __dirname + '/dist',
        filename: '[name].js'
    },
    //通过配置将加载器绑定到RegExp(正则表达式)
    module: {
        rules: [
            //对所有的css使用style-loader和css-loader
            {
                test: /\.css$/,
                use: [ 'style-loader', 'css-loader' ]
            }
        ]
    },
    //使用html模板插件
    plugins: [
        new htmlPlugin({
            minify: {
                removeAttributeQuotes:true
            },
            hash:true,
            template: __dirname + '/src/index.html'
        })
    ]
}

执行webpack打包后:
这里写图片描述
可以看到生成了dist文件夹,dist文件夹中并没有css,这是因为css被打包到了entry.js中,所有的引用的资源都是以js的形式被引用。

注意:

loader的使用是有顺序的,是从后向前,从右向左的。 比如我们使用先使用css-loader是因为要将css插入到页面的style标签中,style-loader是识别插入后的css中的url等。。。

3. 图片的坑

3.1 css中的图片处理

3.1.1基本处理

在src目录下新建一个images文件夹,把图片放入images文件夹。

在index.html文件中增加一个放置div的标签(需要注意的是这里修改的是src下的index.html文件,不是dist下的,这点新手很容易弄混,要格外注意),代码如下

<div id="hcd"></div>

编写css文件,设置hcd盒子的背景

#hcd {
    width: 400px;
    height: 400px;
    background-image: url(./img/IMG_2009.JPG);
}

3.1.2 file-loader,url-loader,img-loader

npm install --save-dev file-loader url-loader img-loader
  • file-loader

    解决引用路径的问题,拿background样式用url引入背景图来说,我们都知道,webpack最终会将各个模块打包成一个文件,因此我们样式中的url路径是相对入口html页面的,而不是相对于原始css文件所在的路径的。这就会导致图片引入失败。这个问题是用file-loader解决的,file-loader可以解析项目中的url引入(不仅限于css),根据我们的配置,将图片拷贝到相应的路径,再根据我们的配置,修改打包后文件引用路径,使之指向正确的文件。

    用file-loader会打包图片,不会增加图片的体积
    这里写图片描述

  • url-loader

    如果图片较多,会发很多http请求,会降低页面性能。这个问题可以通过url-loader解决。url-loader会将引入的图片编码,生成dataURl。相当于把图片数据翻译成一串字符。再把这串字符打包到文件中,最终只需要引入这个文件就能访问图片了。当然,如果图片较大,编码会消耗性能。因此url-loader提供了一个limit参数,小于limit字节的文件会被转为DataURl(64位的编码),大于limit的还会使用file-loader进行copy在内部引用了file-loader,所以想用url-loader必须引用file-loader

    用base64不会打包图片,但是会增加文件的体积
    这里写图片描述

  • img-loader
    https://www.npmjs.com/package/img-loader
    需要配合url-loader或者file-loader一起使用,img-loader是可以根据不同的图片类型进行不同的设置
    压缩打包的图片,原来的图片是132k的,压缩后只有57.4k
    这里写图片描述

用file-loader,http请求图片可以起到一定的缓存作用,当有图片重复时,不会再次加载了
用url-loader,代码每次都会出现,增加代码的体积,影响HTML和js的大小

3.1.3配置url-loader

webpack.config.js文件

const path = require('path');
const htmlPlugin= require('html-webpack-plugin');

module.exports = {
    entry: {
        entry: __dirname + '/src/entry.js'
    },
    output: {
        path: __dirname + '/dist',
        filename: '[name].js'
    },
    //通过配置将加载器绑定到RegExp(正则表达式)
    module: {
        rules: [
            //对所有的css使用style-loader和css-loader
            {
                test: /\.css$/,
                use: [ 'style-loader', 'css-loader' ]
            },
            //对图片使用url-loader
            {
                test: /\.(img|jpg|png)/i,
                use:[{
                    loader: 'url-loader',
                    //通过options给url-loader设置参数
                    options: {
                        //图片小于5000b就变为base64位编码
                        limits: 5000//将超出limit的图面放到dist目录下的images
                        outputPath:'images/'
                    }
                }]
            }
        ]
    },
    plugins: [
        new htmlPlugin({
            minify: {
                removeAttributeQuotes:true
            },
            hash:true,
            template: __dirname + '/src/index.html'
        })
    ]
}

直接使用webpack打包就可以了

3.1.4我们引入图片一般分为3种方式

  1. 在css中引入(layer.less)

  2. 在入口的index.html文件中引入

  3. 在HTML模板文件中引入

Webpack.config.js
1.file-loader

1   //file-loader
2      {
3                   test:   /\.(png|gif|jpe?g|svg)$/i,
4                   loader: 'file-loader',
5                   // 设置编译后图片的地址和名称
6                   // 放在outpath.path:__dirname+'/dist'下的assets文件夹下
7                   // [文件名]-[5位的hash].[文件后缀]
8                   options: {
9                        name: 'assets/[name]-[hash:5].[ext]'
10                  }  
11        }

2.url-loader

1   //  url-loader
2    {
3                  test:   /\.(png|gif|jpe?g|svg)$/i,
4                   loader: 'url-loader',
5                   //设置参数
6                   //limit表示img大于140k的用http请求,小于140k的用base64
7                   // 设置编译后图片的地址和名称
8                   // 放在outpath.path:__dirname+'/dist'下的assets文件夹下
9                   // [文件名]-[5位的hash].[文件后缀]
10                  options: {
11                            limit:1400000,
12                       name: 'assets/[name]-[hash:5].[ext]'
13                  }  
14   }

3.img-loader

1   //img-loader(图片压缩需要和url-loader或者file-loader一起使用)
2    {
3         test:   /\.(png|gif|jpe?g|svg)$/i,
4         loaders:[
5                 'url-loader?limit=1400&name=assets/[name]-[hash:5].[ext]',
6                  'img-loader'
7          ]
8   }               

3.2 CSS分离与图片路径处理

3.2.1 把CSS从JavasScript代码中分离出来

extract-text-webpack-plugin 我们将利用这个plugin解决,但是webpack官方其实并不建议这样作,他们认为CSS就应该打包到JavasScript当中以减少http的请求数。但现实中的需求往往不是我们前端能控制的,有些需求是我们不能控制的,分离CSS就是这样一个既合理由不合理的需求。
API:https://www.npmjs.com/package/extract-text-webpack-plugin

安装:

npm install --save-dev extract-text-wabpack-plugin

配置plugin

const path = require('path');
const htmlPlugin= require('html-webpack-plugin');
// 引用插件
const extractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {
    entry: {
        entry: __dirname + '/src/entry.js'
    },
    output: {
        path: __dirname + '/dist',
        filename: '[name].js'
    },
    module: {
        rules: [
            {
                test: /\.css$/,
                    //对所有的css使用插件的extract方法
                use: extractTextPlugin.extract({
                    fallback: 'style-loader',
                    use:'css-loader'
                })
            },
            {
                test: /\.(img|jpg|png)/i,
                use:[{
                    loader: 'url-loader',
                    options: {
                        limits: 5000
                    }
                }]
            }
        ]
    },
    plugins: [
        new htmlPlugin({
            minify: {
                removeAttributeQuotes:true
            },
            hash:true,
            template: __dirname + '/src/index.html'
        }),
        //初始化extract-text-webpack-plugin,设置打包后分离的css在打包文件dist的路径位置
        new extractTextPlugin('/style/index.css')
    ]
}

3.22图片路径问题

利用extract-text-webpack-plugin插件很轻松的就把CSS文件分离了出来,但是CSS路径并不正确
我们将使用publicPath解决

publicPath:是在webpack.config.js文件的output选项中,主要作用就是处理静态文件路径的。
我们在output中设置
webpack.config.js


const path = require('path');
const htmlPlugin= require('html-webpack-plugin');
const extractTextPlugin = require('extract-text-webpack-plugin');
//设置对象
const website = {
    //是你本机的ip或者是你devServer热更新配置的IP和端口。或者上线后的图片网址,
    publicPath: 'http://192.168.0.118:1717/'
};
module.exports = {
    entry: {
        entry: __dirname + '/src/entry.js'
    },
    output: {
        path: __dirname + '/dist',
        filename: '[name].js',
        //给所有打包的资源的路径都设置为我们想要的path
        publicPath:website.publicPath
    },
     。。。。。
}

3.3 处理html中的图片

在webpack中是不喜欢你使用标签 img 来引入图片的,但是我们作前端的人特别热衷于这种写法,国人也为此开发了一个:html-withimg-loader。他可以很好的处理我们在html 中引入图片的问题。
安装

npm install html-withimg-loader --save

配置loader

    {   
        //对所用的html文件使用loader
        test: /\.(htm|html)$/i,
         use:[ 'html-withimg-loader'] 
    }

4.使用Less

首先安装Less的服务

npm install --save-dev less

安装less-loader

 npm install --save-dev less-loader

loader的配置

    //判断所有的less
     {
          test: /\.less$/,
          //顺序是先使用less-loader转为css,后用css-loader插入style标签,最后是用style-loader解析
          use: [{
              loader: 'style-loader'
          },{
              loader: 'css-loader'
          },{
              loader: 'less-loader'
          }]
      }

我们编写一个less文件:

@base :#000;
#gogo{
    width:300px;
    height:300px;
    background-color:@base;
}

这里#gogo是层的ID名称。@base是我们设置的变量名称。

引入到我们entery.js文件中

import less from './css/black.less';

执行webpack命令就可以了

将less生产的css文件分离出来

利用上面讲的extract-text-webpack-plugin
loader配置方法

   {
       test: /\.less$/,
       use: extractTextPlugin.extract({
           fallback: 'style-loader',
           use: ['css-loader','less-loader']
       })
   }

5.使用sass

安装SASS打包的loader
这里需要 在项目目录下用npm安装两个包。node-sass和sass-loader
node-sass:因为sass-loader依赖于node-sass,所以需要先安装node-sass

npm install --save-dev node-sass

sass-loader:

 npm install --save-dev sass-loader

编写loader配置

{
       test: /\.scss$/,
        use: [{
            loader: "style-loader" // creates style nodes from JS strings
        }, {
            loader: "css-loader" // translates CSS into CommonJS
        }, {
            loader: "sass-loader" // compiles Sass to CSS
        }]
}

使用和less基本是一样的

6.使用loader的注意事项

loader的使用是有顺序的,是从后向前,从右向左的。 比如我们使用先使用css-loader是因为要将css插入到页面的style标签中,style-loader是识别插入后的css中的url等。。。
如果有了less-loader(sass-loader)就要先使用less-loader,因为要先将less或是sass转为css

7.自动处理CSS3属性前缀

PostCSS :
PostCSS是一个CSS的处理平台,它可以帮助你的CSS实现更多的功能,但是今天我们就通过其中的一个加前缀的功能,初步了解一下PostCSS。

安装:

需要安装两个包postcss-loader 和autoprefixer(自动添加前缀的插件)

npm install --save-dev postcss-loader autoprefixer

postcss.config.js

postCSS推荐在项目根目录(和webpack.config.js同级),建立一个postcss.config.js文件。
这里写图片描述
内容为:

//引用postcss的自动补充插件
module.exports = {
    plugins:[
        require('autoprefixer')
    ]
}

编写loader

对postcss.config.js配置完成后,我们还需要在webpack.config.js中编写我们的loader配置

{
      test: /\.css$/,
      use: [
            {
              loader: "style-loader"
            }, {
              loader: "css-loader"
            }, {
               //注意位置,首先使用的是postcss-loader来补全css(loader是从后先前读的)
              loader: "postcss-loader"
            }
      ]
}

提取css

    {
         test: /\.css$/,
         use: extractTextPlugin.extract({
             fallback: 'style-loader',
             //注意位置,首先使用的是postcss-loader来补全css(loader是从右向左读的)
             use:['css-loader','postcss-loader']
         })
     },

8.消除未使用的css

像Bootstrap这样的框架往往会带有很多CSS。在项目中通常我们只使用它的一小部分。就算我们自己写CSS,随着项目的进展,CSS也会越来越多,有时候需求更改,带来了DOM结构的更改,这时候我们可能无暇关注CSS样式,造成很多CSS的冗余。

PurifyCSS

使用PurifyCSS可以大大减少CSS冗余,比如我们经常使用的BootStrap(140KB)就可以减少到只有35KB大小。这在实际开发当中是非常有用的。

安装PurifyCSS-webpack

从名字你就可以看出这是一个插件,而不是loader。所以这个需要安装还需要引入。 PurifyCSS-webpack要以来于purify-css这个包,所以这两个都需要安装。

npm install --save-dev purifycss-webpack purify-css

配置

webpack.config.js
头部的引用:

//因为我们要检查html的所有的DOM,已确定是否有多余的css所以webpack.config.js的首部引入glod
const glob = require('glob');
//引用purifycss-webpack 插件
const purifyPlugin = require('purifycss-webpack');

具体的插件配置:

plugins: [
     new purifyPlugin({
            // paths表示我们要查找的html(绝对路径下的)模板
            paths: glob.sync(path.join(__dirname,'src/*html'))
      })
 ]

再执行webapck命令 会发现多余的css在打包后的css文件中找不到了

9.配置js压缩

现在你写的JS代码,在上线之前,都是需要进行压缩的,在没有webpack和gulp这些工具前,你可能需要找一个压缩软件或者在线进行压缩,在Webpack中可以很轻松的实现JS代码的压缩,它是通过插件的方式实现的,这里我们就先来引入一个uglifyjs-webpack-plugin(JS压缩插件,简称uglify)。

虽然uglifyjs是插件,但是webpack版本里默认已经集成,不需要再次安装。

我们需要在webpack.config.js中引入uglifyjs-webpack-glugin插件

const uglify = require('uglifyjs-webpack-plugin');

引入后在plugins配置里new一个 uglify对象就可以了,代码如下。

 plugins:[
      new uglify()
  ],

10.ES6语法的转译

转译工具babel
Babel中在webpack中的使用
http://babeljs.cn/docs/setup/#webpack

node的path的用法
http://nodejs.cn/api/path.html#path_path_resolve_paths

基本配置

安装:
Babel安装:

npm install --save –dev babel-loader babel-core

es2015安装

npm install bable-preset-es2015

文档结构:
这里写图片描述

Webpack.config.js

var htmlWebpackPlugin = require('html-webpack-plugin');
// 因为要用绝对路径,所以我们使用node.js自带的path
var path = require('path');

module.exports = { 
    entry:'./src/app.js',
    output:{
        path:__dirname+'/dist',
        filename:'js/[name]-bundle.js'
    },
    // 通过配置将加载器绑定到RegExp(正则表达式)
    //ES6的转译插件babel
    module:{
        loaders:[
            {
                //检测所有的js文件
                test: /\.js$/, 
                //使用babel-loader
                loader: "babel-loader",
                //不用使用(使用绝对路径)的数组
                //path.resolve可以得出绝对路径
                    exclude:[
                                       path.resolve(__dirname,'node_modules/'),
                   path.resolve(__dirname,'dist/')
                                  ],
                // 只是src下的js使用(使用绝对路径)
                //因为es6是不断更新的,babel转译es6是有不同版本的,这里采用‘es2015’版,也可以在loader?presets='es2015'表示
                query:{
                    presets:['es2015']
                }
            }
        ]
    },
    plugins:[
        new htmlWebpackPlugin({
            template:'index.html',
            filename:'index.html',
            title:'this is C',
            inject:'body'
        })
    ]
}

如果你觉得看着麻烦:

{
    test:/\.(jsx|js)$/,
    use:{
        loader:'babel-loader',
        options:{
            presets:[
                "es2015"
            ]
        }
    },
    exclude:/node_modules/
}

.babelrc配置

虽然Babel可以直接在webpack.config.js中进行配置,但是考虑到babel具有非常多的配置选项,如果卸载webapck.config.js中会非常的雍长不可阅读,所以我们经常把配置写在.babelrc文件里。
在项目根目录新建.babelrc文件。
这里写图片描述
将配置写在其中

{
    "presets": [
        "es2015"
    ]
}

webpack.config.js里的loader配置

{
    test:/\.(jsx|js)$/,
    use:{
        loader:'babel-loader',
    },
    exclude:/node_modules/
}

ENV

现在网络上已经不流行babel-preset-es2015,现在官方推荐使用的是babel-preset-env
下载:

npm install --save-dev babel-preset-env

然后修改.babelrc里的配置文件。其实只要把之前的es2015换成env就可以了。

{
    "presets":["env"]
}

10.处理模板文件

API:http://webpack.github.io/docs/list-of-loaders.html#templating

html模板插件
npm install html-loader –save-dev

jade模板
npm install jade-loader –save-dev

ejs模板
npm install ejs-loader –save-dev

目录结构:
这里写图片描述
Layer.html
这里写图片描述
layerEjs.ejs
这里写图片描述

Layer.js

//引入html模板  其实是字符串
import tpl from './layer.html';
//引入ejs模板  其实是函数(用时可能会需要传入参数)
import ejs from './layerEjs.ejs';
function layer(){
    return{
        name:'layer',
        tpl:tpl,
        ejs:ejs
    }
}
Export default layer

app.js

import './css/common.css';
import layer from './components/layer/layer.js';
import less from './components/layer/layer.less';
const app = function(){
    var dom = document.getElementById('app');
    var newLayer = layer();
    //模板其实就是newLayer.tpl属性,将模板当做字符串
    dom.innerHTML =  newLayer.tpl;

    var ejsdom = document.getElementById('ejsdiv');
    //向ejs模板中传递参数
    ejsdom.innerHTML = newLayer.ejs({
        name:'hcd',
        arr:['apple','xiaomi','honor']
    })
}
new app();

webnpack.config.js
在原来的基础上加上
这里写图片描述
结果:
这里写图片描述
可以看到都在页面上显示出来了

猜你喜欢

转载自blog.csdn.net/haochangdi123/article/details/78316815