Webpack 配置示例

Webpack 作为前端构建工具,对于大型网站开发,大大提升了开发效率。要使用webpack需要先安装webpack工具;

先来看一个最简单的命令

$ webpack main.js bundle.js

该命令将 main.js 输出到 bundle.js 。

通常,都不会这样直接使用使用,而是在项目根目录下进行打包配置,配置文件默认为webpack.config.js。

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

之后,直接在命令行中使用 webpack 就能进行打包了!

除了直接使用 webpack 进行打包之外,还可以对打包命令进行一些选择性的配置:

  • webpack – for building once for development
  • webpack -p – for building once for production (minification)
  • webpack --watch – for continuous incremental build
  • webpack -d – to include source maps
  • webpack --colors – for making things pretty

同样,这些配置也可以写进 package.json 配置文件中

// package.json
{
  // ...
  "scripts": {
    "dev": "webpack-dev-server --devtool eval --progress --colors",
    "deploy": "NODE_ENV=production webpack -p"
  },
  // ...
}

1. entry

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

entry 除了使用一个单一的 js 文件之外,还可以使用多个 js 文件;

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

2. Babel-loader

Loader 是源代码转换预处理器(more info). 例如, Babel-loader 可以将 JSX/ES6 转换成 JS 文件. 参见官方文档:loaders.

// main.jsx is a JSX file.

const React = require(‘react‘);
const ReactDOM = require(‘react-dom‘);

ReactDOM.render(
  <h1>Hello, world!</h1>,
  document.querySelector(‘#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‘
      },
    ]
  }
};

module.loaders 用于指定 loaders. 上面的代码片段使用了 babel-loader,也用到了babel-preset-es2015babel-preset-react 用来转换 ES6 和 React。也可以使用如下的query的方式来配置:

module: {
  loaders: [
    {
      test: /\.jsx?$/,
      exclude: /node_modules/,
      loader: ‘babel‘,
      query: {
        presets: [‘es2015‘, ‘react‘]
      }
    }
  ]
}

3. CSS-loader

Webpack 使我们可以通过 require 引用一个css文件并结合css-loader处理之后输出成一个模块。

main.js

require(‘./app.css‘);

app.css

body {
  background-color: blue;
}

index.html

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

webpack.config.js

module.exports = {
  entry: ‘./main.js‘,
  output: {
    filename: ‘bundle.js‘
  },
  module: {
    loaders:[
      { test: /\.css$/, loader: ‘style-loader!css-loader?modules‘ },
    ]
  }
};

注意,这里使用了两个loader来转换css文件。 CSS-loader 用来读取CSS文件, Style-loader用来插入样式到网页中. 不同的loader用 ! 来连接.

在浏览器中浏览网页,index.html中已经插入了样式表。

<head>
  <script type="text/javascript" src="bundle.js"></script>
  <style type="text/css">
    body {
      background-color: blue;
    }
  </style>
</head>

4. Image loader

Webpack 还可以通过 require 引用图片文件。

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);

index.html

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

webpack.config.js

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

这里使用了 url-loader 来转换图片文件. 如果图片小于 8192 bytes 将会被转换成 Data URL; 否则将会被转换成普通的URL. ? 用来给url-loader传入参数.

两张不同大小的图片会被转换成不同的格式如下:

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

5. CSS Module

css-loader?modules 表示打开 CSS Modules 的功能。它表示module中定义的css样式默认是局部作用域;如果需要转换成全局作用域可以通过 :global(.abc) (more info)

index.html

<html>
<body>
  <h1 class="h1">Hello World</h1>
  <h2 class="h2">Hello Webpack</h2>
  <div id="example"></div>
  <script src="./bundle.js"></script>
</body>
</html>

app.css

.h1 {
  color:red;
}

:global(.h2) {
  color: blue;
}

main.jsx

var React = require(‘react‘);
var ReactDOM = require(‘react-dom‘);
var style = require(‘./app.css‘);

ReactDOM.render(
  <div>
    <h1 className={style.h1}>Hello World</h1>
    <h2 className="h2">Hello Webpack</h2>
  </div>,
  document.getElementById(‘example‘)
);

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‘]
        }
      },
      {
        test: /\.css$/,
        loader: ‘style-loader!css-loader?modules‘
      }
    ]
  }
};

6. UglifyJs Plugin

Webpack 有插件支持用来扩展更多的需求。 UglifyJs Plugin 将会最小化输出的js文件.

main.js

var longVariableName = ‘Hello‘;
longVariableName += ‘ World‘;
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 o="Hello";o+=" World",document.write("<h1>"+o+"</h1>")

注意:如果需要结合使用到postcss,webpack.config.js文件需要有一些小的修改如下:

var values = require("postcss-modules-values");
var webpack = require(‘webpack‘);
var uglifyJsPlugin = webpack.optimize.UglifyJsPlugin;

module.exports = {
    entry: __dirname + "/index.js",
    output: {
        path:"public",
        publicPath: "/",
        filename: "bundle.js"
    },
    module: {
        loaders:[
            {
                test: /\.js$/,
                exclude: /node_modules/,
                loader:‘babel-loader‘
            },
            {
                test: /\.css$/,
                loader: "style-loader!css-loader?modules!postcss-loader"
            }
        ]
    },
    plugins:[
        new uglifyJsPlugin({
            compress:{
                warnings: false
            }
        }),
        new webpack.LoaderOptionsPlugin({
            test:/\.css$/,
            options: {
                postcss:[values]
            }
        })
    ]
};

7. HTML Webpack Plugin and Open Browser Webpack Plugin

下面来看如何加载第三方插件

html-webpack-plugin 可以创建index.html, open-browser-webpack-plugin 可以打开一个浏览器窗口当 Webpack 加载完成之后。

npm install html-webpack-plugin open-browser-webpack-plugin webpack-dev-server --save

main.js

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

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‘
    })
  ]
};

运行 webpack-dev-server.

$ webpack-dev-server

现在不需要手动创建index.html文件,也不需要去打开浏览器窗口了,一切由webpack为我们包办了!

可能遇到的错误: Error: Cannot find module ‘webpack/lib/node/NodeTemplatePlugin‘ ,解决办法:在项目中重新安装webpack。

8. Environment flags

可以通过一些配置来对开发环境和正式环境进行一些不同的操作;

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]
};

运行webpack打包并输入环境变量配置:

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

# Windows
$ set DEBUG=true
$ webpack-dev-server

process.env 默认为一个空对象,通过 env DEBUG=true命令 为env.DEBUG赋值。

9. Code splitting

对于大型web网站,不可能将所有的js文件都放到一个文件中一次性加载, Webpack 允许我们将js文件进行分割。

首先,你需要使用 require.ensure 来定义分割点 (official document)

// main.js
require.ensure([‘./a‘], function(require) {
  var content = require(‘./a‘);
  document.open();
  document.write(‘<h1>‘ + content + ‘</h1>‘);
  document.close();
});

require.ensure 告诉 Webpack,./a.js 文件应该从bundle.js文件中分割出来并编译到一个单独的文件中。

// a.js
module.exports = ‘Hello World‘;

现在webpack将会自动进行编译打包,不需要再进行额外的配置。

webpack.config.js

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

从表象上看,没有任区别,但实际上webpack将main.js和a.js编译到两个不同的文件中了,分别是bundle.js和1.bundle.js文件,当需要用到的时候再加载1.bundle.js文件;

10. Code splitting with bundle-loader

另一个代码分割的方法是使用 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‘) 告诉 Webpack 需要从另外的js文件中去加载 a.js。webpack的行为将和上面相同。

11. Common chunk

当多个script文件需要使用到相同的chunk的时候,可以将这个公用的模块通过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>
    <div id="a"></div>
    <div id="b"></div>
    <script src="init.js"></script>
    <script src="bundle1.js"></script>
    <script src="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: [
    new CommonsChunkPlugin(‘init‘)
  ]
}

12. Vendor chunk

也可以通过 CommonsChunkPlugin 来分割提取出js库。

main.js

var $ = require(‘jquery‘);
$(‘h1‘).text(‘Hello World‘);

index.html

<html>
  <body>
    <h1></h1>
    <script src="vendor.js"></script>
    <script src="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: [
    new webpack.optimize.CommonsChunkPlugin(/* chunkName= */‘vendor‘, /* filename= */‘vendor.js‘)
  ]
};

更新:最新的webpack中,CommonsChunkPlugin有所改变,应修改如下:

    plugins: [
        new CommonsChunkPlugin({
            name: ‘vendor‘,
            filename: "vendor.js"})
    ]

如果你希望一个module可以作为一个变量使用到其它地方,比如使用jQuery的 $ ,我们可以在任何地方使用而不需要通过 require("jquery"),这就需要用到 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: [
    new webpack.ProvidePlugin({
      $: "jquery",
      jQuery: "jquery",
      "window.jQuery": "jquery"
    })
  ]
};

13. Exposing global variables

如果我们想使用一些全局变量,但又不想把它们包含在webpack中,这时候可以通过在webpack.config.js中 配置 externals 来实现 official document

data.js.

var data = ‘Hello World‘;

将data数据暴露成全局变量

// 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‘
  }
};

现在,通过 var data = require(‘data‘) 可以将data.js输出到模块变量中。但实际上data是一个全局变量。

// main.jsx
var data = require(‘data‘);
var React = require(‘react‘);
var ReactDOM = require(‘react-dom‘);

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

14. Hot Module Replacement

Hot Module Replacement (HMR) 当网页发生改变的时候,不需要手动刷新页面。结合webpack-dev-server有两种方式来打开 HMR。

(1) 在命令中指定 --hot 和 --inline

$ webpack-dev-server --hot --inline

Meaning of the options:

  • --hot: adds the HotModuleReplacementPlugin and switch the server to hot mode.
  • --inline: embed the webpack-dev-server runtime into the bundle.
  • --hot --inline: also adds the webpack/hot/dev-server entry.

(2) 配置 webpack.config.js.

  • add new webpack.HotModuleReplacementPlugin() to the plugins field
  • add webpack/hot/dev-server and webpack-dev-server/client?http://localhost:8080 to the entry field

webpack.config.js

var webpack = require(‘webpack‘);
var path = require(‘path‘);

module.exports = {
  entry: [
    ‘webpack/hot/dev-server‘,
    ‘webpack-dev-server/client?http://localhost:8080‘,
    ‘./index.js‘
  ],
  output: {
    filename: ‘bundle.js‘,
    publicPath: ‘/static/‘
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin()
  ],
  module: {
    loaders: [{
      test: /\.jsx?$/,
      exclude: /node_modules/,
      loader: ‘babel-loader‘,
      query: {
        presets: [‘es2015‘, ‘react‘]
      },
      include: path.join(__dirname, ‘.‘)
    }]
  }
};
Now launch the dev server.
$ webpack-dev-server

在浏览器中打开 http://localhost:8080 查看网页。保持网页打开,对网页修改一些内容,观察浏览器是否发生改变;

App.js

import React, { Component } from ‘react‘;

export default class App extends Component {
  render() {
    return (
      <h1>Hello World</h1>
    );
  }
}

index.js

import React from ‘react‘;
import ReactDOM from ‘react-dom‘;
import App from ‘./App‘;

ReactDOM.render(<App />, document.getElementById(‘root‘));

index.html

<html>
  <body>
    <div id=‘root‘></div>
    <script src="/static/bundle.js"></script>
  </body>
</html>

15. React router

参考 React-router 官方示例

+---------------------------------------------------------+
| +---------+ +-------+ +--------+                        |
| |Dashboard| | Inbox | |Calendar|      Logged in as Jane |
| +---------+ +-------+ +--------+                        |
+---------------------------------------------------------+
$ webpack-dev-server --history-api-fallback 

参考连接:

时间: 2024-08-09 02:41:59

Webpack 配置示例的相关文章

webpack配置这一篇就够

最近看了一篇好文,根据这个文章重新梳理了一遍webpack打包过程,以前的一些问题也都清楚了,在这里分享一下,同时自己也做了一些小的调整 原文链接:http://www.jianshu.com/p/42e11515c10f git项目地址:https://github.com/gengchen528/webpackSample 更多前端内容可以到:http://www.bloggeng.com/ 写在前面的话 阅读本文之前,先看下面这个webpack的配置文件,如果每一项你都懂,那本文能带给你的

华为MSTP负载均衡配置示例

8.6.7   MSTP负载均衡配置示例 本示例拓扑结构如图8-38所示,SwitchA.SwitchB.SwitchC和SwitchD都运行MSTP.它们彼此相连形成了一个环网,因为在SwitchA与SwitchB之间,以及SwitchC与SwitchD之间都存在冗余链路.为实现VLAN2-VLAN10和VLAN11-VLAN20的流量负载分担,本示例采用MSTP协议配置了两个MSTI,即MSTI1和MSTI2. 图8-38  MSTP配置示例 1.    配置思路分析 (1)在四台交换机创建

tinc vpn简单配置示例扩展(一)——跨越三层网络

tinc vpn简单配置示例扩展(一)--跨越三层网络 在tinc vpn简单配置示例(http://watertoeast.blog.51cto.com/8489855/1711649)一文中,构建tinc VPN的两台机器同属一个局域网(如图一),这样的场景基本与实际应用情况不符.今天对简单示例进行扩展,使构建vpn的两台主机跨越三层网络边界(如图二). 图一 tinc vpn in lan 图二 tinc VPN跨越三层网络边界 如图二所示,PC02的IP地址变成了172.16.1.6,与

webpack 配置的探索

1   webpack  --display-modules  --display-chunks  可以展示出 打包的全部trunk webpack 配置 生成分析文件 webpack --profile --json > stats.json到一下网址分析 http://chrisbateman.github.io/webpack-visualizer/ 分析 CommonsChunkPlugin

Cisco ODR配置示例

静态路由的缺点是,必须手工配置,同时在网络拓扑变化后需要手工更新:动态路由的缺点是,它们需要占用网络带宽和路由器资源.在包含数百个分支站点的中央-分支网络,采用静态路由时配置工作量将非常大,而采用动态路由时将占用大量的资源. 在这种情况下,我们采用第三种方式--按需路由(ODR,On Demand Routing).ODR是Cisco的私有协议,它使用CDP在分支路由器和中央路由器之间传输网络信息.它的优点是,比动态路由协议开销小得多,比静态路由协议配置量少得多.而它的缺点就是,只适合于中央-分

DB2 HADR 配置示例

介绍 DB2的HA可以在OS级别使用专门的HA来实现,也可使用DB2内置的HADR来实现,且配置和管理很简单. 一个HADR环境需要两台数据库服务器:主数据库服务器(primary)和备用数据库服务器(standby,处于standby角色的数据库不能够被访问).当主数据库中发生事务操作时,会同时将日志文件通过TCP/IP协议传送到备用数据库服务器,然后备用数据库对接受到的日志文件进行重放(Replay),从而保持与主数据库的一致性.当主数据库发生故障时,备用数据库服务器可以接管主数据库服务器的

华为IPv4静态路由配置示例

IPv4静态路由配置示例 组网需求 如图1所示,属于不同网段的主机通过几台Switch相连,要求不配置动态路由协议,使不同网段的任意两台主机之间能够互通. 图1 配置IP静态路由组网图 配置思路 采用如下的思路配置IPv4静态路由: 创建VLAN并配置各接口所属VLAN,配置各VLANIF接口的IP地址,实现相邻设备网络互通. 在各主机上配置IP缺省网关,在各台Switch上配置IPv4静态路由或者静态缺省路由,实现不配置动态路由协议,使不同网段的任意两台主机之间能够互通. 操作步骤 1.配置各

LVS NAT模型配置示例

1.LVS-NAT基于Cisco的LocalDirector.VS/NAT不需要在RealServer上做任何设置,其只要能提供一个tcp/ip的协议栈即可,甚至其无论基于什么OS. 2.基于VS/NAT,所有的入站数据包均由Director进行目标地址转换后转发至内部的RealServer,RealServer响应的数据包再由Director转换源地址后发回客户端. 3.VS/NAT模式不能与netfilter兼容,因此,不能将VS/NAT模式的Director运行在netfilter的保护范

LVS DR模型配置示例

要让路由知道哪台主机是Director,进行选择: 1.VIP:MAC(Director VIP) -- MAC绑定,但未必可行,例如路由是运营商的. 2.arptables 3.kernel parameter(常用此配置): arp_ignore:定义接收到ARP请求时的响应级别: 0:默认级别,只要本机配置有相应的地址,就给予响应: 1:只有当请求目标地址是请求到达接口上配置的地址,才给予响应: arp_announce:定义将自己的地址向外通告时的通告级别: 0:默认级别,将本机任何接口