webpack demo详解

  20 Jul 2017


如何使用

首先全局安装 webpack 和 webpack-dev-server

npm i -g webpack webpack-dev-server

克隆下https://github.com/GITxiangzhang/webpack-demos.git (本文全部demo具体代码都在这上面)

git clone https://github.com/GITxiangzhang/webpack-demos.git

npm install

https://github.com/GITxiangzhang/webpack-demos.git下有整理的demo 启动webpack-dev-server 后在浏览器访问相应的端口查看

cd demo01
webpack-dev-server

什么是webpack

现今的很多网页其实可以看做是功能丰富的应用,它们拥有着复杂的JavaScript代码和一大堆依赖包。为了简化开发的复杂度,前端社区涌现出了很多好的实践方法

  • 模块化,让我们可以把复杂的程序细化为小的文件;
  • 类似于TypeScript这种在JavaScript基础上拓展的开发语言:使我们能够实现目前版本的JavaScript不能直接使用的特性,并且之后还能能装换为JavaScript文件使浏览器可以识别;
  • Scss,less等CSS预处理器

这些改进确实大大的提高了我们的开发效率,但是利用它们开发的文件往往需要进行额外的处理才能让浏览器识别,而手动处理又是非常繁琐的,这就为WebPack类的工具的出现提供了需求

WebPack可以看做是模块打包机:它做的事情是,分析你的项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(Scss,TypeScript等),并将其打包为合适的格式以供浏览器使用。

WebPack和Grunt以及Gulp相比有什么特性

其实Webpack和另外两个并没有太多的可比性,Gulp/Grunt是一种能够优化前端的开发流程的工具,而WebPack是一种模块化的解决方案,不过Webpack的优点使得Webpack可以替代Gulp/Grunt类的工具。

Grunt和Gulp的工作方式是:在一个配置文件中,指明对某些文件进行类似编译,组合,压缩等任务的具体步骤,这个工具之后可以自动替你完成这些任务。

webpack1

Webpack的工作方式是:把你的项目当做一个整体,通过一个给定的主文件(如:index.js),Webpack将从这个文件开始找到你的项目的所有依赖文件,使用loaders处理它们,最后打包为一个浏览器可识别的JavaScript文件。

webpack2

如果实在要把二者进行比较,Webpack的处理速度更快更直接,能打包更多不同类型的文件。


demo01 入口文件

webpack 通过入口文件,自动识别项目依赖的其他文件,打包到bundle.js中

//main.js
document.write('<h1>hello world</h1>')

index.html

<html>
  <body>
    <script type="text/javascript" src="bundle.js"></script>
  </body>
</html>

webpack 根据webpack.config.js 配置文件去打包生成 bundle.js

//webpack.config.js
module.exports={
  entry:'./main.js',
  output:{
  filename:'bundle.js'
  }
}

demo2多个入口文件

webpack支持多个入口文件,这种方式对于多页app是很有用的。

//main1.js
document.write('<h1>Hello World</h1>');
//main2.js
document.write('<h2>Hello webpack</h2>');

index.html

<html>
  <body>
    <script src="bundle1.js"></script>
    <script src="bundle2.js"></script>
  </body>
</html>

webpack.config.js

module.exports={
  entry:{
  bundle1:"./main1.js",
  bundle2:"./main2.js"
  },
  output:{
  filename:'[name].js'
  }
}

demo03 bable-loader

Loaders是webpack中最让人激动人心的功能之一了。通过使用不同的loader,webpack通过调用外部的脚本或工具可以对各种各样的格式的文件进行处理,比如说分析JSON文件并把它编译为JavaScript文件, 或者说把下一代的JS文件(ES6,ES7)编译为现代浏览器可以识别的JS文件。或者说对React的开发而言,合适的Loaders可以把React的JSX文件编译为JS文件。

Loaders需要单独安装并且需要在webpack.config.js下的modules关键字下进行配置,Loaders的配置选项包括以下几方面:

  • test:一个匹配loaders所处理的文件的拓展名的正则表达式(必须)
  • loader:loader的名称(必须)
  • include/exclude:手动添加必须处理的文件(文件夹)或屏蔽不需要处理的文件(文件夹)(可选);
  • query:为loaders提供额外的设置选项(可选)

如demo03

//main.jsx
const React= require('react');
const ReactDOM=require('react-dom');

ReactDOM.render(
    <h1>hello world!!</h1>,
    document.getElementById('wrapper')

);
//index.html
<html>
  <body>
    <div id="wrapper"></div>
    <script src="bundle.js"></script>
  </body>
</html>
//webpack.config.js
module.exports = {
  entry: './main.jsx',
  output: {
    filename: 'bundle.js'
  },
  module: {
    loaders:[
      {
        test: /\.js[x]?$/,
        exclude: /node_modules/,
        loader: 'babel-loader?presets[]=es2015&presets[]=react',
      },
    ]
  }
};

demo04 css-loader

webpack 允许在js中引入css文件,用CSS-loader 预处理css文件。

main.js

require('./app.css')

app.css

body{
 background-color:bule;
}

index.html

<html>
  <head>
    <script type="text/javascript" src="bundle.js"></script>
  </head>
  <body>
    <h1>Hello World</h1>
  </body>
</html>

webpack.config.js

module.exprots={
  entry:'./main.js',
  output:{
  filename:'bundle.js'
  },
  module:{
  loaders:[{
  test:/\.css$/,loader:'style-loader!css-loader'
  }]
  }


};

在这,你必须要两个loaders 去编译css文件,CSS-loader用来读取css文件,Style-loader 将样式标签插入到页面中。两个loader用!连接。


demo05 Image loader

webpack 支持在js中引入images

main.js

var img1 = document.createElement("img");
img1.src = require("./small.png");
document.body.appendChild(img1);

var img2 = document.createElement("img");
img2.src = require("./big.png");
document.body.appendChild(img2);

webpack.config.js

module.exprots={
  entry:'./main.js',
  output:{
  filename:'bundle.js'
  },
  module:{
  loaders:[
  { test: /\.(png|jpg)$/, loader: 'url-loader?limit=8192'}
  ]
  }


};

url-loader 可用来编译图片,如果图片大小小于limit设定的值(8192bytes),他将会被编译成一个base 64格式的数据型url,如果大于设定, 编译成正常的url,loader加参数用?

<img src="data:image/png;base64,iVBOR...uQmCC">
<img src="4853ca667a2b8b8844eb2693ac1b2578.png">

demo06 CSS Module

CSS Module

demo07 UglifyJs Plugin

webpack 有丰富的插件库来扩展它的功能。例如 UglifyJs 插件 用来合并压缩js代码。

main.js

var longVariableName="阿里";
longVariableName+="巴巴";
document.write("<h1>"+longVariableName+"</h1>")

webpack.config.js

var webpack=require('webpack');
var uglifyJsPlugin=webpack.optimize.UglifyJsPlugin;

module.exports={
  entry: './main.js',
  output:{
  filename:'bundle.js'
  },
  plugins:[
  new uglifyJsPlugin({
  compress:{
  warnings:false
  }
  })
  ]
};

运行查看 main.js 会被编译成

var t="Hello";t+=" World",document.write("<h1>"+t+"</h1>")

webpack插件库点这里!!


HTML Webpack Plugin and Open Browser Webpack Plugin

html-webpack-plugin 插件会创建一个index.html ,open-browser-webpack-plugin插件webpack运行时候新选项卡自动打开浏览器。

webpack.config.js

var HtmlwebpackPlugin = require('html-webpack-plugin');
var OpenBrowserPlugin = require('open-browser-webpack-plugin');
module.exports = {
  entry: './main.js',
  output: {
    filename: 'bundle.js'
  },
  plugins: [
    new HtmlwebpackPlugin({
      title: 'Webpack-demos',
      filename: 'index.html'
    }),
    new OpenBrowserPlugin({
      url: 'http://localhost:8080'
    })
  ]
};

设置环境变量

你可以利用环境变量来控制特定代码的输出

main.js

document.write('<h1>Hello World</h1>');

if (__DEV__) {
  document.write(new Date());
}

webpack.config.js

var webpack = require('webpack');

var devFlagPlugin = new webpack.DefinePlugin({
  __DEV__: JSON.stringify(JSON.parse(process.env.DEBUG || 'false'))
});

module.exports = {
  entry: './main.js',
  output: {
    filename: 'bundle.js'
  },
  plugins: [devFlagPlugin]
};

$ set DEBUG=true $ webpack-dev-server


Code Splitting 分批打包、按需下载

Code Splitting


Exposing global variables