2016-10-22 webpack

webpack入门

Here !

Node环境下,

Webpack :它做的事情是,分析你的项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(Scss,TypeScript等),
并将其打包为合适的格式以供浏览器使用。
和gulp,grunt差不多,webpack就是模块加载器兼打包工具

  It can beused as a module bundler similar to Browserify, and do much more.

  $ browserify main.js > bundle.js
  # be equivalent to
  $ webpack main.js bundle.js //和browserify等价


  Webpack常用命令:
  webpack 最基本的启动webpack命令
  webpack -w 提供watch方法,实时进行打包更新
  webpack -p 对打包后的文件进行压缩
  webpack -d 提供SourceMaps,方便调试
  webpack --colors 输出结果带彩色,比如:会用红色显示耗时较长的步骤
  webpack --profile 输出性能数据,可以看到每一步的耗时
  webpack --display-modules 默认情况下 node_modules 下的模块会被隐藏,加上这个参数可以显示这些被隐藏的模块
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

全局安装webpack和webpack-dev-server:

npm install –g webpack webpack-dev-server

webpack-dev-server是一个小型的node.js

Express服务器,它使用webpack-dev-middleware中间件来为通过webpack打包生成的资源文件提供Web服务。

它还有一个通过Socket.IO连接着webpack-dev-server服务器的小型运行时程序。
webpack-dev-server发送关于编译状态的消息到客户端,客户端根据消息作出响应。

直接敲命令:webpack-dev-server 打开本机浏览器输入 http://127.0.0.1:8080就可以看到你页面效果;

在webpack模块打包中最好先安装依赖,好多组件需要用,使用命令:npm install;

可以按照阮一峰做的demo来学习:
我fork的git地址:https://github.com/fairyly/webpack-demos#demo01-entry-file-source
怎么使用里面都有介绍的,不过都是英文,马马虎虎应该可以看懂;

说个例子,一个小项目下三个文件:

    For example, main.js is an entry file.
    // main.js
    document.write('<h1>Hello World</h1>');
    index.html

    <html>
    <body>
      <scripttype="text/javascript"src="bundle.js"></script>
    </body>
    </html>
    Webpack follows webpack.config.js to build bundle.js.
    // webpack.config.js
    module.exports = {
    entry:'./main.js',//entry用来定义入口文件
    output: {           //output用于定义构建后的文件的输出,有path和filename;
      filename:'bundle.js'
    }
    };
    //entry中定义构建多个文件时,filename可以对应的更改为[name].js用于定义不同文件构建后的名字
    $ webpack   //这一个命令就在目录下生成一个bundle.js文件
    $ webpack-dev-server
    Launch theserver, visit http://127.0.0.1:8080 .

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

Babel-loader ,babel就是转码器;

    看demo:
    main.jsx is a JSX file.
    constReact=require('react');
    constReactDOM=require('react-dom');

    ReactDOM.render(
      <h1>Hello, world!</h1>,
      document.querySelector('#wrapper')
    );
    index.html

    <html>
      <body>
        <divid="wrapper"></div>
        <scriptsrc="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'
          },
        ]
      }
    };
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

这时候要配置module,loaders:
模块的加载相关,我们就定义在module.loaders中。这里通过正则表达式去匹配不同后缀的文件名,然后给它们定义不同的加载器
Loaders的配置选项包括以下几方面:
test:一个匹配loaders所处理的文件的拓展名的正则表达式(必须)
loader:loader的名称(必须)
include/exclude:手动添加必须处理的文件(文件夹)或屏蔽不需要处理的文件(文件夹)(可选);
query:为loaders提供额外的设置选项(可选)

CSS-loader 加载css

    配置module:

    module: {
        loaders:[
          { test:/\.css$/, loader:'style-loader!css-loader' },
        ]
      }
1
2
3
4
5
6
7

Image loader 加载图片

    配置module:
    module: {
        loaders:[
          { test:/\.(png|jpg)$/, loader:'url-loader?limit=8192' }
        ]
      }
    Limit=8192,如果图片大小小于8192字节,将转换成base64编码格式显示,如果大于就按照正常的url显示;
1
2
3
4
5
6
7

CSS Module 加载css 模块

    {
      test:/\.css$/,
      loader:'style-loader!css-loader?modules'
    }

1
2
3
4
5

UglifyJs Plugin js压缩组件

    Js压缩插件配置:
    var webpack =require('webpack');
    var uglifyJsPlugin = webpack.optimize.UglifyJsPlugin;
    module.exports = {
      entry:'./main.js',
      output: {
        filename:'bundle.js'
      },
      plugins: [
        newuglifyJsPlugin({
          compress: {
            warnings:false
          }
        })
      ]
    };

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

HTML Webpack Plugin andOpen Browser Webpack Plugin webpack的html和打开浏览器插件

    var HtmlwebpackPlugin =require('html-webpack-plugin');
    var OpenBrowserPlugin =require('open-browser-webpack-plugin');

    module.exports = {
      entry:'./main.js',
      output: {
        filename:'bundle.js'
      },
      plugins: [
        newHtmlwebpackPlugin({
          title:'Webpack-demos',
          filename:'index.html'
        }),
        newOpenBrowserPlugin({
          url:'http://localhost:8080'
        })
      ]
    };
    $ Webpack 
    Run webpack-dev-server.
    $ webpack-dev-server

    这时候不需要写一个index.html文件,也不需要手动打开浏览器输入http://localhost:8080,webpack会做这些事情;
    
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

Environment flags 环境标志

    main.js

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

    if (__DEV__) {
      document.write(newDate());
    }
    index.html

    <html>
    <body>
      <scriptsrc="bundle.js"></script>
    </body>
    </html>
    webpack.config.js

    var webpack =require('webpack');

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

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

    # Linux & Mac
    $ env DEBUG=true webpack-dev-server

    # Windows
    $ set DEBUG=true
    $ webpack-dev-server
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

Code splitting 代码分离

    you use require.ensure to define a split point. (official document)
    // main.js
    require.ensure(['./a'], function(require) {
      var content =require('./a');
      document.open();
      document.write('<h1>'+ content +'</h1>');
      document.close();
    });
    require.ensure tells Webpack that ./a.js should be separated from bundle.js and built into a single chunk file.
    // a.js
    module.exports ='Hello World';
    Now Webpack takes care of the dependencies, outputfiles and runtime stuff. You don't have to put any redundancy into your index.html and webpack.config.js.
    <html>
      <body>
        <scriptsrc="bundle.js"></script>
      </body>
    </html>
    webpack.config.js

    module.exports = {
      entry:'./main.js',
      output: {
        filename:'bundle.js'
      }
    };
    Launch theserver.

    $ webpack-dev-server 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

Code splitting withbundle-loader

    Another wayof code splitting is using bundle-loader.

    // main.js

    // Now a.js is requested, it will be bundled into another file
    var load =require('bundle-loader!./a.js');

    // To wait until a.js is available (and get the exports)
    //  you need to async wait for it.
    load(function(file) {
      document.open();
      document.write('<h1>'+ file +'</h1>');
      document.close();
    });
    require('bundle-loader!./a.js') tells Webpack to load a.js from another chunk.
    Now Webpack will build main.js into bundle.js, and a.js into 1.bundle.js.
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

Common chunk 通用模块

    When multiscripts have common chunks, you can extract the common part into a separatefile with CommonsChunkPlugin.

    // main1.jsx
    var React =require('react');
    var ReactDOM =require('react-dom');

    ReactDOM.render(
      <h1>Hello World</h1>,
      document.getElementById('a')
    );

    // main2.jsx
    var React =require('react');
    var ReactDOM =require('react-dom');

    ReactDOM.render(
      <h2>Hello Webpack</h2>,
      document.getElementById('b')
    );
    index.html

    <html>
      <body>
        <divid="a"></div>
        <divid="b"></div>
        <scriptsrc="init.js"></script>
        <scriptsrc="bundle1.js"></script>
        <scriptsrc="bundle2.js"></script>
      </body>
    </html>
    webpack.config.js

    var CommonsChunkPlugin =require("webpack/lib/optimize/CommonsChunkPlugin");
    module.exports = {
      entry: {
        bundle1:'./main1.jsx',
        bundle2:'./main2.jsx'
      },
      output: {
        filename:'[name].js'
      },
      module: {
        loaders:[
          {
            test:/\.js[x]?$/,
            exclude:/node_modules/,
            loader:'babel-loader',
            query: {
              presets: ['es2015', 'react']
            }
          },
        ]
      },
      plugins: [
        newCommonsChunkPlugin('init.js')
      ]
    }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58

Vendor chunk

    You can alsoextract the vendor libraries from a script into a separate file withCommonsChunkPlugin.

    main.js

    var $ =require('jquery');
    $('h1').text('Hello World');
    index.html

    <html>
      <body>
        <h1></h1>
        <scriptsrc="vendor.js"></script>
        <scriptsrc="bundle.js"></script>
      </body>
    </html>
    webpack.config.js

    var webpack =require('webpack');

    module.exports = {
      entry: {
        app:'./main.js',
        vendor: ['jquery'],
      },
      output: {
        filename:'bundle.js'
      },
      plugins: [
        newwebpack.optimize.CommonsChunkPlugin(/* chunkName= */'vendor', /* filename= */'vendor.js')
      ]
    };
    If you want a module available as variable in everymodule, such as making $ and jQuery available in every module without writing require("jquery"). You should use ProvidePlugin (Official doc).
    // main.js
    $('h1').text('Hello World');


    // webpack.config.js
    var webpack =require('webpack');

    module.exports = {
      entry: {
        app:'./main.js'
      },
      output: {
        filename:'bundle.js'
      },
      plugins: [
        newwebpack.ProvidePlugin({
          $:"jquery",
          jQuery:"jquery",
          "window.jQuery":"jquery"
        })
      ]
    };
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

Exposing globalvariables暴露全局变量

    For example, we have a data.js.
    var data ='Hello World';
    We can expose data as a global variable.
    // webpack.config.js
    module.exports = {
      entry:'./main.jsx',
      output: {
        filename:'bundle.js'
      },
      module: {
        loaders:[
          {
            test:/\.js[x]?$/,
            exclude:/node_modules/,
            loader:'babel-loader',
            query: {
              presets: ['es2015', 'react']
            }
          },
        ]
      },
      externals: {
        // require('data') is external and available
        //  on the global var data
        'data':'data'
      }
    };
    Now, you require data as a module variable in your script. but it actually is a globalvariable.
    // main.jsx
    var data =require('data');
    var React =require('react');
    var ReactDOM =require('react-dom');

    ReactDOM.render(
      <h1>{data}</h1>,
      document.body
    );

    resolve

    webpack在构建包的时候会按目录的进行文件的查找,resolve属性中的extensions数组中用于配置程序可以自行补全哪些文件后缀:

     resolve:{
         extensions:['','.js','.json']
     }
    然后我们想要加载一个js文件时,只要require('common')就可以加载common.js文件了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

working study......