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 developmentwebpack -p
– for building once for production (minification)webpack --watch
– for continuous incremental buildwebpack -d
– to include source mapswebpack --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-es2015 和 babel-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]
- }
- })
- ]
- };
备注: UglifyJsPlugin还可以对一些指定的变量不进行混淆
- plugins: [
- new webpack.optimize.UglifyJsPlugin({
- mangle: {
- except: ['$super', '$', 'exports', 'require']
- //以上变量‘$super’, ‘$’, ‘exports’ or ‘require’,不会被混淆
- },
- compress: {
- warnings: false
- }
- })
- ]
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提取到单独的文件中。
- // JQ01.js
- var $ = require("jquery");
- $('#a').text("001");
- // JQ02.js
- var $ = require("jquery");
- $('#b').text("002");
上面的两个不同的组件中,都同时需要用到 JQuery,甚至会有更多的组件也会如此,此时可以将 JQuery 提取出来,放置到一个公共的 js 文件中。
index.html
- <html>
- <body>
- <div id="a"></div>
- <div id="b"></div>
- <script src="vendor.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: "./JQ01.js",
- bundle2: "./JQ02.js",
- vendor: ["jquery"] // option
- },
- output: {
- filename: "[name].js"
- },
- plugins: [
- new CommonsChunkPlugin({
- name: 'vendor',
- filename: "vendor.js"
- })
- ]
- };
随着库越来越大,vendor文件也变得越来越大,于是考虑打包成两个vendor,把和react相关的库打包成一个vendor,其他的库打包成另外一个vendor。
- ...
- entry: {
- "vendor1": ["react", "react-dom", "react-router", "react-router-redux", "react-redux", "redux"],
- "vendor2": ["jquery"],
- "app": "./js/index.js"
- },
- ...
- plugins: [
- new webpack.optimize.CommonsChunkPlugin({
- names: ["vendor2", "vendor1"],
- minChunks: Infinity
- })
- ],
- ...
有两个需要注意的地方:
- 在CommonsChunkPlugin里面,vender的顺序要反着来,要和加载顺序相反。比如你想按vendor1,vendor2的顺序加载,entry里面写的是vendor1,vendor2,在CommonsChunkPlugin里面要写vendor2,vendor1。
- output.filename一定不要写死了,要配置成可替换的,类似filename: '[name].js'形式。
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 CommonsChunkPlugin({
- name: 'vendor',
- filename: "vendor.js"})
- ]
- };
ProvidePlugin
如果你希望一个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 theplugins
field - add
webpack/hot/dev-server
andwebpack-dev-server/client?http://localhost:8080
to theentry
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
参考连接:
- Webpack docs
- webpack-howto, by Pete Hunt
- Diving into Webpack, by Web Design Weekly
- Webpack and React is awesome, by Christian Alfoni
- Browserify vs Webpack, by Cory House
- React Webpack cookbook, by Christian Alfoni
- Webpack Demos
Webpack 官方文档 : http://webpack.github.io/docs/configuration.html
Webpack 配置示例的更多相关文章
- Webpack配置示例和详细说明
/* * 请使用最新版本nodejs * 默认配置,是按生产环境的要求设置,也就是使用 webpack -p 命令就可以生成正式上线版本. * 也可以使用 webpack -d -w 命令,生成用于开 ...
- webpack配置示例
var webpack = require('webpack'); var commonsPlugin = new webpack.optimize.CommonsChunkPlugin('commo ...
- webpack配置这一篇就够
最近看了一篇好文,根据这个文章重新梳理了一遍webpack打包过程,以前的一些问题也都清楚了,在这里分享一下,同时自己也做了一些小的调整 原文链接:http://www.jianshu.com/p/4 ...
- vue-cli中webpack配置详解
vue-cli是构建vue单页应用的脚手架,命令行输入vue init <template-name> <project-name>从而自动生成的项目模板,比较常用的模板有we ...
- webpack 配置分离css插件
以css配置示例,less与sass同理 1. 使用旧版的ExtractTextPlugin插件 安装 npm install extract-text-webpack-plugin@next --s ...
- 通用、封装、简化 webpack 配置
通用.封装.简化 webpack 配置 现在,基本上前端的项目打包都会用上 webpack,因为 webpack 提供了无与伦比强大的功能和生态.但在创建一个项目的时候,总是免不了要配置 webpac ...
- Element源码:项目初始化和webpack配置
0x00.项目初始化 由于整个过程像素级 copy element,所以将不使用vue-cli初始化项目. 创建项目 新建一个空的文件夹,使用npm init 来初始化项目,并安装vue模块. 修改目 ...
- [webpack] 配置react+es6开发环境
写在前面 每次开新项目都要重新安装需要的包,简单记录一下. 以下仅包含最简单的功能: 编译react 编译es6 打包src中入口文件index.js至dist webpack配置react+es6开 ...
- webpack配置详解
webpack配置详解 先点个赞吧,再挨个点下面的连接,觉得不值这个赞的回来骂我啊. Webpack傻瓜式指南(一) Webpack傻瓜指南(二)开发和部署技巧 Webpack傻瓜式指南 原生的官网详 ...
随机推荐
- 【RL系列】Multi-Armed Bandit笔记补充(二)
本篇的主题是对Upper Conference Bound(UCB)策略进行一个理论上的解释补充,主要探讨UCB方法的由来与相关公式的推导. UCB是一种动作选择策略,主要用来解决epsilon-gr ...
- Bootstrap学习--栅格系统
响应式布局页面:即同一套页面可以兼容不同分辨率的设备. Bootstrap依赖于栅格系统实现响应式布局,将一行均分为12个格子,可以指定元素占几个格子. 实现过程 1.定义容器,相当于之前的table ...
- nice和renice命令详解
基础命令学习目录首页 进程调度是linux中非常重要的概念.linux内核有一套高效复杂的调度机制,能使效率极大化,但有时为了实现特定的要求,需要一定的人工干预.比如,你希望操作系统能分配更多的CPU ...
- maven实战读书笔记(一)
环境变量设置 MAVEN_HOME:G:\maven-3.2\apache-maven-3.2.5 Path: G:\maven-3.2\apache-maven-3.2.5\bin 其实正确的设置应 ...
- sprint2(第二天)
昨天没有想到餐桌的功能,今天加到展板.然后今天我们完成了餐桌模板,可以实现添加桌子的桌号.人数.修改和删除功能.不过由于今天学校网络不是很好,晚上我们clone了很久都没clone下来,所以没有上传代 ...
- 软件工程-东北师大站-第九次作业(PSP)
1.本周PSP 2.本周进度条 3.本周累计进度图 代码累计折线图 博文字数累计折线图 4.本周PSP饼状图
- 【请仔细核对Git地址】关于代码量排名的说明
1.截至2017年3月14日,1623班级代码统计情况如下: 2.代码量排名是基于码云的git地址统计的,请大家仔细核对以下个人地址,如有问题请及时联系我. 20162301 20162302 201 ...
- 场景调研 persona
1.姓名:王涛 2.年龄:22 3.收入:基本无收入 4.代表用户在市场上的比例和重要性:王涛为铁道学生.本软件的用户主要是学生和老师,尤其是广大的铁大学子,所以此典型用户的重要性不言而喻,而且比例相 ...
- ORACLE_SQL
--建立学生表create table Student ( Sno char(9) primary key, Sname char(20)unique, Sex ...
- java 数字转中文
java代码 数字转中文,该方法只做了对int型整数的转换 private static String numberToChinese(int number) { String[] numbers = ...