首页 > 代码库 > webpack入门和实战(二):全面理解和运用loader和plugins

webpack入门和实战(二):全面理解和运用loader和plugins

您的阅读目录:
  • 一、理解webpack加载器loader
  • 二、理解less-loader加载器的使用
  • 三、理解babel-loader加载器的使用
  • 四、webpak命令行常见使用的操作
  • 五、用webpack内置组件UglifyJsPlugin来压缩js和css
  • 六、html-webpack-plugin(生成自定义html页面)
  • 七、extract-text-webpack-plugin(独立打包样式文件)
  • 八、webpack打包多个资源文件
  • 九、webpack对图片的打包
回到顶部
一、理解webpack加载器loader
1.1、什么是loader?
webpack的设计理念,所有资源都是“模块”,webpack内部实现了一套资源加载机制。loaders 用于转换应用程序的资源文件,他们是运行在nodejs下的函数 使用参数来获取一个资源的来源并且返回一个新的来源(资源的位置),例如你可以使用loader加载器可以快速编译预处理器(less,sass,coffeeScript)。
1.2、使用loader
  • 安装loader
$ npm install xxx-loader --save-dev
加载器包括:style-loader、css-loader、less-loader、sass-loader、jsx-loader、url-loader、babel-loader、file-loader等等;各个加载器都有自己的功能,你可以根据项目需要来安装相应的加载器;
  • 配置loader

安装完各个loader后,我们就需要配置一下我们的webpack.config.js,载入我们的loader。

// webpack.config.jsmodule.exports = {    entry: path.join(__dirname, src/entry.js),    output: {        path: path.join(__dirname, out),        publicPath: "./out/",        filename: bundle.js    },    // 新添加的module属性    module: {        loaders: [            {test: /\.js$/, loader: "babel"},            {test: /\.css$/, loader: "style!css"},            {test: /\.(jpg|png)$/, loader: "url?limit=8192"},            {test: /\.scss$/, loader: "style!css!sass"}        ]    }};

我们主要看看module的loaders。loaders是一个数组,里面的每一个对象都用正则表达式,对应着一种配对方案。Webpack提供了一套加载器,比如css-loader,less-loader,style-loader,url-loader等,用于将不同的文件加载到js文件中,比如url-loader用于在js中加载png/jpg格式的图片文件;css/style loader用于加载css文件;less-loader加载器是将less编译成css文件;不同的处理器通过!分隔并串联起来。这里的loader是可以省略掉-loader这样的,也就是原本应该写成style-loader!css-loader!sass-loader.

回到顶部
二、理解less-loader加载器的使用
我们先来理解下less-loader加载器,其他的sass-loader也是一个意思,less-loader加载器是把css代码转化到style标签内,动态插入到head标签内;
我们先来看看我项目的结构如下:
技术分享

因此你需要根据package.json来初始化本项目的依赖模块,执行命令:npm install;

其中less/main.less 文件如下代码:

@base:red;body{    margin:10px;    background-color:@base;}

现在我想通过html-webpack-plugin插件动态生成 html页面及引入index.js 和 生成 index.js文件;

webpack.config.js代码配置如下:

var path = require(path);var HtmlwebpackPlugin = require(html-webpack-plugin);//定义了一些文件夹的路径var ROOT_PATH = path.resolve(__dirname);var SRC_PATH = path.resolve(ROOT_PATH, src);var BUILD_PATH = path.resolve(ROOT_PATH, build);module.exports = {  entry: SRC_PATH + "/js/index.js",  output: {    filename: "build.js",    path: BUILD_PATH  },  module: {    loaders: [      {test: /\.less$/,loader: "style!css!less"}    ]  },  resolve: {    extensions: [‘‘, .js, .jsx]  },  plugins: [    new HtmlwebpackPlugin({      title: Hello World app,      filename: index.html,      inject: true,      hash: true    })  ]};

在项目的根目录运行webpack,即可动态生成html文件和js文件,打开生成后的index.html即可看到css生效了,且css被动态内链到head标签内了。

技术分享

上面是使用webpack打包;现在我们再来看看使用第二种方案来打包~

使用gulp来进行打包

我们知道使用gulp来打包的话,那么我们需要在根目录下需要新建 Gulpfile.js;同时需要安装依赖包gulp和gulp-webpack,执行命令:npm install gulp gulp-webpack --save-dev

因此我们这边Gulpfile.js的源码如下:

var gulp = require(gulp);var webpack = require("gulp-webpack");var webpackConfig = require("./webpack.config.js");gulp.task(webpack, function () {    var myConfig = Object.create(webpackConfig);    return gulp        .src(./js/index.js)        .pipe(webpack(myConfig))        .pipe(gulp.dest(./build));});// 注册缺省任务gulp.task(default, [webpack]);

然后修改一下webpack.config.js代码,只需要将output中push屏蔽掉,如下所示:

output: {    filename: "build.js"   // path: BUILD_PATH},

即可,然后再在命令行中输入gulp即可生成build/build.js和index.html了,如下所示:

技术分享

less-loader项目源码地址:http://download.csdn.net/detail/wdlhao/9613213
回到顶部
三、理解babel-loader加载器的使用
babel-loader加载器能将ES6的代码转换成ES5代码,这使我们现在可以使用ES6了。
我们先来看看我项目的结构如下:

技术分享

首先安装babel-loader。执行命令:npm install babel-loader –save-dev
当然你也需要根据package.json来初始化本项目的其他依赖模块,执行命令:npm install;
如上安装完后,我们在根目录node_modules会生成文件,如下所示:
技术分享
src/js/a.js,完全是遵照es6的语法,代码如下:
//es6的语法let LOADER = true; //module.exports = LOADER;class Project {  constructor(name) {    this.name = name;  }  start() {    return "Project " + this.name + " starting";  }}var project = new Project("Journal");let projectName = project.start(); // "Project Journal starting"module.exports = "安装es6语法输出:"+LOADER+","+projectName;

src/js/index.js,执行入口,用于输出es6代码结果,代码如下:

var aMoudle = require(./a);console.log(aMoudle);

现在我们可以在webpack.config.js里面moudle.loaders配置加载器了,代码如下:

var path = require(path);var HtmlwebpackPlugin = require(html-webpack-plugin);//定义了一些文件夹的路径var ROOT_PATH = path.resolve(__dirname);var SRC_PATH = path.resolve(ROOT_PATH, src);var BUILD_PATH = path.resolve(ROOT_PATH, build);module.exports = {  entry: SRC_PATH + "/js/index.js",  output: {    filename: "build.js",    path: BUILD_PATH  },  module: {    loaders: [      {test: /\.js$/, loader: babel}    ]  },  resolve: {    extensions: [‘‘, .js, .jsx]  },  plugins: [    new HtmlwebpackPlugin({      title: Hello babel-loader,      filename: index.html,      inject: true,      hash: true    })  ]};

最后生成的build/index.html代码如下:

<!DOCTYPE html><html>  <head>    <meta charset="UTF-8">    <title>Hello babel-loader</title>  </head>  <body>  <script type="text/javascript" src=http://www.mamicode.com/"build.js?906bc2a0e6ca45cdeddd"></script></body></html>

index.html在控制台的打印效果为:

技术分享

说明用babel-loader加载器来执行es6代码,执行成功。
babel-loader项目源码地址:http://download.csdn.net/detail/wdlhao/9613208
回到顶部
四、webpak命令行常见使用的操作
 安装 webpack 后,可以使用 webpack 这个命令行工具。主要命令: webpack <entry> <output> 。可以切换到包含webpack.config.js的目录运行命令:
  •     webpack: 启动 执行一次开发时的编译
  •     webpack  -w:如果你想当改变一个文件而让webpack实时编译
  •     webpack -p: 执行一次生成环境的编译(压缩)
  •      webpack  -d:对文件进行解压缩,提供source map,方便调式代码方便调试文件
  •     webpack --config customconfig.js:如果你想把默认的配置文件webpack.config.js改成自定义文件
  •     webpack --watch :在开发时持续监控增量编译(很快)
  •     webpack --display-error-details 显示更多报错信息
  •     webpack --display-chunks 展示编译后的分块
  •      webpack --colors 显示静态资源的颜色
  •     webpack --progress 显示编译进度
  •     webpack --display-reasons 显示更多引用模块原因
  •     webpack --profile 输出性能数据,可以看到每一步的耗时 
  •     webpack --display-modules 默认情况下node_modules下的模块会被隐藏,加上这个参数可以显示这些被隐藏的模块
  •     webpack --sort-chunks-by,--sort-assets-by,--sort-modules-by 将modules/chunks/assets进行列表排序
  •     webpack -help,查看webpack帮忙文档
现在我们以babel-loader项目为例,展示webpack常用命令行的使用方法;

我们下面来了解下 webpack -w,如下所示:

技术分享

比如我在js文件里面随便增加一点代码后,保存后,再刷新页面即可可以看到代码生效了,无需重新运行webpack或者gulp,使用webpack -w 可以实时打包。

 webpack -p 的含义是对进行打包后的文件进行压缩代码;比如我在之前使用chrome看打包后的代码如下:

 技术分享

如上可以看到,代码是未压缩的,但是当我在控制台命令行中运行 webpack -p 命令后,如下所示:

 技术分享
我们现在再到控制台上看下代码变成已经压缩后的代码了,如下所示:
技术分享
webpack  -d 是提供未压缩之前的源码 方便代码中的调式;如下所示:
技术分享

当我运行如上所示后,我们再来看看刚才已经压缩后的代码变成什么样子呢?如下所示:

技术分享

如上代码可以看到 我们进行压缩后的代码,通过运行 webpack -d 命令后,即可还原未压缩的代码,这样的话就可以方便我们线上调式代码了。同时生成了一个map文件,bulid.js.map主要是方便调试。
webpack --watch :在开发时持续监控增量编译(很快)与webpack -w效果一样。如图为修改了代码之后的表现:
技术分享
webpack --display-chunks 展示编译后的分块
技术分享
webpack --display-modules 显示node_modules下的隐藏模块
技术分享
webpack -help,查看webpack帮忙文档
技术分享
 
回到顶部
五、用webpack内置组件UglifyJsPlugin来压缩js和css
webpack已经内嵌了uglifyJS来完成对JS与CSS的压缩混淆,无需引用额外的插件。
压缩代码如下:
new webpack.optimize.UglifyJsPlugin({    //压缩代码   compress: {       warnings: false   },   except: [$super, $, exports, require]    //排除关键字})

这里需要注意的是压缩的时候需要排除一些关键字,不能混淆,比如$或者require,如果混淆的话就会影响到代码的正常运行。
webpack.config.js代码改为如下:

技术分享
var path = require(path);var HtmlwebpackPlugin = require(html-webpack-plugin);var webpack = require("webpack");module.exports = {  entry: {    index:./src/index.js  },  output: {    path: path.resolve(__dirname, "./build"),    filename: "[name].js"  },  module: {    loaders: [        {test: /.css$/, loader: style!css}    ]  },   //添加我们的插件 会自动生成一个html文件  plugins: [    new HtmlwebpackPlugin({      title: inner plugin:UglifyJsPlugin,      filename: index.html,      inject: true,      hash: true,      minify:{ //压缩HTML文件        removeComments:true,    //移除HTML中的注释        collapseWhitespace:true    //删除空白符与换行符      }    }),    new webpack.optimize.UglifyJsPlugin({    //压缩代码       compress: {           warnings: false       },       except: [$super, $, exports, require]    //排除关键字    })  ]}
View Code
继续运行下webpack可以看到js已经被压缩了;注意:但是貌似对es6的语法不能压缩~
根据内置组件webpack进行代码混淆,主要是针对生成后的js代码,如index.js,代码如下:

 技术分享

根据外部组件html-webpack-plugin中minify进行代码压缩,主要是针对index.html,用于清除里面的注释、空白符与换行符等。结果如下:

技术分享

压缩js和css项目的源码地址:http://download.csdn.net/detail/wdlhao/9613216

回到顶部
六、html-webpack-plugin(生成自定义html页面)
这个插件用来简化创建服务于 webpack bundle 的 HTML 文件,尤其是对于在文件名中包含了 hash 值,而这个值在每次编译的时候都发生变化的情况。你既可以让这个插件来帮助你自动生成 HTML 文件,也可以使用 lodash 模板加载生成的 bundles,或者自己加载这些 bundles。自动生成满足要求的html文件。
使用 npm 安装这个插件:npm install html-webpack-plugin --save-dev
首先来看看项目的目录结构如下:
技术分享
运行命令 npm install 把依赖包加载出来;
接着在 webpack.config.js配置如下:
var path = require(path);var HtmlwebpackPlugin = require(html-webpack-plugin);//定义了一些文件夹的路径var ROOT_PATH = path.resolve(__dirname);var SRC_PATH = path.resolve(ROOT_PATH, src);var BUILD_PATH = path.resolve(ROOT_PATH, build);module.exports = {  entry: SRC_PATH + "/js/index.js",  output: {    path: BUILD_PATH,    filename: index.js//输出的文件名 合并以后的js会命名为index.js  },  //添加我们的插件 会按要求自动生成一个html文件  module: {    loaders: [        {test: /.less$/, loader: "style!css!less"}    ]  },  plugins: [    new HtmlwebpackPlugin({      title: Hello World app//生成新的html页面的title;    })  ]};
在项目中的根目录下 运行 webpack 就能生成build文件夹了,里面会自动生成 两个文件 index.html和index.js文件;
index.html代码如下:
<!DOCTYPE html><html>  <head>    <meta charset="UTF-8">    <title>Hello World app</title>  </head>  <body>  <script type="text/javascript" src=http://www.mamicode.com/"index.js"></script></body></html>

标题title就是我们配置上的;且合并了依赖的js文件;我们可以直接在本地访问index.html 可以看到能打印出依赖的文件js代码了;可以看到可以解决依赖的问题;

html-webpack-plugin 还支持如下配置:

  • title: 用于生成的HTML文件的标题。
  • filename: 用于生成的HTML文件的名称,默认是index.html。你可以在这里指定子目录。
  • template: 模板文件路径,支持加载器,比如 html!./index.html
  • inject: true | ‘head‘ | ‘body‘ | false ,注入所有的资源到特定的 template 或者 templateContent 中,如果设置为 true 或者 body,所有的 javascript 资源将被放置到 body 元素的底部,‘head‘ 将放置到 head 元素中。
  • favicon: 添加特定的 favicon 路径到输出的 HTML 文件中。
  • minify:{ //压缩HTML文件 
      removeComments:true, //移除HTML中的注释 
      collapseWhitespace:true //删除空白符与换行符
    }
  • hash: true | false, 如果为 true, 将添加一个唯一的 webpack 编译 hash 到所有包含的脚本和 CSS 文件,对于解除 cache 很有用。
  • cache: true | false,如果为 true, 这是默认值,仅仅在文件修改之后才会发布文件。
  • showErrors: true | false, 如果为 true, 这是默认值,错误信息会写入到 HTML 页面中
  • chunks: 允许只添加某些块 (比如,仅仅 unit test 块)
  • chunksSortMode: 允许控制块在添加到页面之前的排序方式,支持的值:‘none‘ | ‘default‘ | {function}-default:‘auto‘
  • excludeChunks: 允许跳过某些块,(比如,跳过单元测试的块)
下面的示例演示了如何使用这些配置:
filename:重命名输出文件及设置;inject:设置输出文件位置;hash:决定是否生成hash值;favicon;favicon路径
webpack.config.js代码如下:
 plugins: [    new HtmlwebpackPlugin({      favicon:./src/img/favicon.ico,  //favicon路径      title: Hello World app,//生成新的html页面的title;      filename: home/home.html,      inject: true,      hash: true    })  ]

然后再在命令行中继续运行webpack命令,可以看到在build下会生成2个目录, 第一个是home/home.html; 第二个是 index.js
再来看下home.html代码如下:

<!DOCTYPE html><html>  <head>    <meta charset="UTF-8">    <title>Hello World app</title>  <link rel="shortcut icon" href=http://www.mamicode.com/"favicon.ico"></head>  <body>  <script type="text/javascript" src=http://www.mamicode.com/"../index.js?f19ff1a103d13247bfb5"></script></body></html>

我们发现在body里面自动添加了外链的js文件并且该js文件带有唯一的hash编码,hash编码可以更好的实现js文件的缓存,加快渲染速度。

webpack-html-webpack-plugin(default)源码地址为:http://download.csdn.net/detail/wdlhao/9613219

minify是用来压缩和清洁html代码

在webpack.config.js中添加,代码如下:

plugins: [    new HtmlwebpackPlugin({      favicon:./src/img/favicon.ico,  //favicon路径      title: Hello World app,//生成新的html页面的title;      filename: home/home.html,      inject: true,      hash: true,      minify:{ //压缩HTML文件           removeComments:true,    //移除HTML中的注释           collapseWhitespace:true    //删除空白符与换行符      }    })  ]

 查看html生成后的文件可以看到已经被压缩了,形式上变成一行了。如图:

技术分享

webpack-html-webpack-plugin(minify)源码地址为:http://download.csdn.net/detail/wdlhao/9613212

回到顶部

七、理解 extract-text-webpack-plugin(独立打包样式文件)

执行安装命令: npm install extract-text-webpack-plugin 
然后再webpack.config.js 加入加载器配置项如下代码:
var path = require(path);var HtmlwebpackPlugin = require(html-webpack-plugin);var ExtractTextPlugin = require(extract-text-webpack-plugin);//定义了一些文件夹的路径var ROOT_PATH = path.resolve(__dirname);var SRC_PATH = path.resolve(ROOT_PATH, src);var BUILD_PATH = path.resolve(ROOT_PATH, build);module.exports = {  entry: SRC_PATH + "/js/index.js",  output: {    filename: "build.js",    path: BUILD_PATH  },  module: {    loaders: [      test:/\.less$/,      loader: ExtractTextPlugin.extract(            css?sourceMap! +            less?sourceMap      )    ]  },  resolve: {    extensions: [‘‘, .js, .jsx]  },  plugins: [   // 内联css提取到单独的styles的css    new ExtractTextPlugin("index.css"),    new HtmlwebpackPlugin({      title: Hello World app,      filename: index.html,      inject: true,      hash: true    })  ]};
在项目的根目录运行 webpack 即可生效;会在build目录下 生成 index.css文件,且在打包后的index.html会自动引入link标签的css;
如下所示:
<!DOCTYPE html><html>  <head>    <meta charset="UTF-8">    <title>Hello World app</title>  <link href=http://www.mamicode.com/"index.css?3a51e24a9f1f95dd46e0" rel="stylesheet"></head>  <body>  <script type="text/javascript" src=http://www.mamicode.com/"build.js?3a51e24a9f1f95dd46e0"></script></body></html>
extract-text-webpack-plugin项目的源码地址:http://download.csdn.net/detail/wdlhao/9613209
回到顶部
八、webpack打包多个资源文件
我们在开发页面的时候,有时候需要有多个入口文件,做到文件是按需加载,这样就可以使用缓存提升性能;那么我们接下来需要如何配置呢?现在我们继续做demo,现在比如我现在的项目文件结构如下:
技术分享
我们直接看 webpack.config.js配置代码变成如下:
entry: {    index:SRC_PATH + "/js/index.js",    main:SRC_PATH + "/js/main.js"  },  output: {    filename: "[name].bundle.js",    path: BUILD_PATH  },

从上面的配置代码我们可以看到 entry现在变成了一个对象了,而对象名也就是key会作为下面output的filename属性的[name]。当然entry也可以是一个数组。

因此我们直接 webpack运行下即可 在build文件下 生成2个入口文件 如上面的截图所示,现在我们可以根据不同的页面 引入不同的入口文件,实现按需加载文件。

webpack打包多个资源文件源码地址如下:http://download.csdn.net/detail/wdlhao/9613221

回到顶部
九、webpack对图片的打包

我现在的项目文件结构如下:

 技术分享

图片是 url-loader来加载的,我们既可以在css文件里url的属性;

首先先安装 url-loader插件: npm install --save-dev url-loader

首先在src/js/index.js文件里面加入如下代码:

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

首先在src/less/main.less文件里面加入如下代码:

@color: red;body {    background:@color;    background:url(../images/1.png) no-repeat;}
src/images/1.png,自己添加的图片;build文件夹是执行webpack之后的生成的内容;
webpack.config.js所有代码如下:
技术分享
var path = require(path);var HtmlwebpackPlugin = require(html-webpack-plugin);var webpack = require("webpack");//定义了一些文件夹的路径var ROOT_PATH = path.resolve(__dirname);var SRC_PATH = path.resolve(ROOT_PATH, src);var BUILD_PATH = path.resolve(ROOT_PATH, build);module.exports = {  entry: {     "index": SRC_PATH + "/js/index.js"  },  output: {    filename: "[name].js",    path: BUILD_PATH  },  module: {    loaders: [      //.css 文件使用 style-loader 和 css-loader 来处理      {        test: /\.less$/,        loader:style!css!less?sourceMap      },      {        test: /\.js$/,         loader: babel      },      {        test: /.(png|jpg)$/,         loader: url?limit=8192&name=images/[hash:8].[name].[ext]//这种写法主要是用来设置图片的存放路径及图片的生成名字如,build/images/43243234234.1.png      }      }    ]  },  resolve: {    extensions: [‘‘, .js, .jsx]  },  plugins: [    new HtmlwebpackPlugin({        title: Hello World app,        filename: index.html,        inject: true,        hash: true    })  ]};
View Code

执行webpack后,在浏览器中查看显示效果,如图所示:

技术分享

至此运用url-loader实现图片打包,并且能够在css中正确运用打包后的图片。

webpack对图片的打包的源码地址为:http://download.csdn.net/detail/wdlhao/9613223
 
 
 

 

 

webpack入门和实战(二):全面理解和运用loader和plugins