请用心练完这16个webpack小例子

16个demo,webpack+react搭配使用
首先教你们2个新技能javascript

步骤

首先,install Webpack 和 webpack-dev-server.css

$ npm i -g webpack webpack-dev-server
# Linux & Mac
$ git clone git@github.com:holidaying/webpack-demos.git

# Windows
$ git clone https://github.com/holidaying/webpack-demos.git
:
$ cd webpack-demos
$ npm install

接下来就能够进行demo演示了.html

$ cd demo01
$ webpack-dev-server

用浏览器访问 http://127.0.0.1:8080.前端

什么是webpack?

Webpack 是前端的打包工具类相似于 Grunt and Gulp.可是有区别,由于它是模块化构建机制,Webpack能够看作是模块打包机:它作的事情是,分析你的项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(Scss,TypeScript等),并将其打包为合适的格式以供浏览器使用。
WebPack和Grunt以及Gulp相比有什么特性
其实Webpack和另外两个并无太多的可比性,Gulp/Grunt是一种可以优化前端的开发流程的工具,而WebPack是一种模块化的解决方案,不过Webpack的优势使得Webpack能够替代Gulp/Grunt类的工具。
Grunt和Gulp的工做方式是:在一个配置文件中,指明对某些文件进行相似编译,组合,压缩等任务的具体步骤,这个工具以后能够自动替你完成这些任务。
更多信息.vue

$ webpack main.js bundle.js

它的配置文件是 webpack.config.js.java

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

有了webpack.config.js,你能够不带参数使用webpacknode

$ webpack

一些命令行选项你应该知道。react

  • webpack – 构建文件
  • webpack -p – 发布
  • webpack --watch – 监听项目
  • webpack -d – 包含 source maps方便调试
  • webpack --colors – 让打包界面更好看

去构建你的项目, 你能够把启动项写进package.jsonjquery

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

目录

  1. 单文件入口
  2. 多文件入口
  3. Babel-loader
  4. CSS-loader
  5. Image loader
  6. CSS Module
  7. UglifyJs Plugin插件
  8. HTML Webpack Plugin and Open Browser Webpack Plugin
  9. Environment flags环境变量
  10. Code splitting代码分割
  11. Code splitting with bundle-loader
  12. Common chunk提取公共文件
  13. Vendor chunk提取公共的第三方代码
  14. externals全局变量
  15. 热模块替代/热更新
  16. React router

Demo01: 单文件入口 (源码)

Webpack会入口文件进行打包成bundle.js.webpack

例子, main.js 是单文件入口.

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

index.html

<html> <body> <script type="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', output: { filename: 'bundle.js' } };

启动服务, 访问 http://127.0.0.1:8080 .

$ webpack-dev-server

Demo02: 多文件入口(源码)

多个入口文件,实用于多个页面的应用

// 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: Babel-loader (源码)

经过使用不一样的loader,webpack经过调用外部的脚本或工具能够对各类各样的格式的文件进行处理(更多信息). 例如, Babel-loader Babel实际上是一个编译JavaScript的平台能够将 JSX/ES6 文件转换成浏览器能够识别的js文件. 官方文档loaders.

main.jsx is a JSX 文件.

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

在 webpack.config.jsmodule.loaders 区域是用来分配loader的. 像上面的代码片断使用了 babel-loader 须要安装插件 babel-preset-es2015 和 babel-preset-react to 编译成 ES6 and React. 能够用query配置参数

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

Demo04: CSS-loader (源码)

Webpack 容许你在js文件中require CSS , 经过 CSS-loader来预处理css文件.

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

可是,你须要使用2中loaders来转换CSS 文件. 第一个是 CSS-loader 来读取CSS文件, 另一个是Style-loader 是将style样式插入到html中。 中间用!链接

启动服务后, index.html 有内部样式.

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

Demo05: Image loader (源码)

Webpack 容许你在js文件中require图片 , 经过 url-loader和file-loader来预处理图片文件.

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,它将会转成base64位的地址; 相反, 它就是普通地址.
参数前是用?链接的

启动服务后, small.png and big.png 将会有一下的地址.

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

Demo06: CSS Module (源码)

css-loader?modules (the query parameter modules) enables the CSS Modules spec.

CSS Module能够开启全局变量和局部变量,:global(...)表示全局变量,能够在全局中使用样式(更多信息)

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

启动服务.

$ webpack-dev-server

访问 http://127.0.0.1:8080 , 你将看到只有第二个 h1 是红的,由于它是局部, 同时 h2 是蓝色的, 由于是h2全局的.

Demo07: UglifyJs Plugin (源码)

Webpack 能够去掉自己附加的东西,优化代码 UglifyJs Plugin will minify output(bundle.js) JS codes.

main.js

var longVariableName = 'Hello'; longVariableName += ' World'; document.write('<h1>' + longVariableName + '</h1>');

index.html

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

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

Demo08: HTML Webpack Plugin and Open Browser Webpack Plugin (源码)

这个例子须要加载三个插件

html-webpack-plugin 建立 index.html ,open-browser-webpack-plugin 打开浏览器

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.启动这个须要node7版本以上

$ webpack-dev-server

不用手写index.html 也不用手动打开浏览器 Webpack 能够为你作这些事.

Demo09: 设置环境变量(源码)

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

main.js

document.write('<h1>Hello World</h1>'); if (__DEV__) { document.write(new Date()); }

index.html

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

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] };
# Linux & Mac
$ env DEBUG=true webpack-dev-server

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

Demo10: Code splitting (源码)

对于大型项目,把全部代码编译到一个文件并非有效的, Webpack 容许你把代码分红好多块. 特别是某种状况下,只须要个别代码这些块能够按需加载。
在commonjs中有一个Modules/Async/A规范,里面定义了require.ensure语法。webpack实现了它,做用是能够在打包的时候进行代码分片,并异步加载分片后的代码。用法以下:
require.ensure([], function(require){
var list = require('./list');
list.show();
});
此时list.js会被打包成一个单独的chunk文件,大概长这样:
1.fb874860b35831bc96a8.js
可读性比较差。我在上一篇结尾也提到了,给它命名的方式,那就是给require.ensure传递第三个参数,如:

require.ensure([], function(require){
var list = require('./list');
list.show();
}, 'list');
这样就能获得你想要的文件名称:
首先,你须要用 require.ensure to 来定义一个分割的点. (官方文档)

// 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';

Now Webpack takes care of the dependencies, output files and runtime stuff. You don't have to put any redundancy into your index.html and webpack.config.js.

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

webpack.config.js

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

地洞服务.

$ webpack-dev-server

在界面上, 你感受不到任何不同的地方. 可是, Webpack 已经把 main.js 和 a.js 编译成(bundle.js 和 1.bundle.js)的块。

Demo11: 经过bundle-loader进行代码分裂 (源码)

dem10是一种,另外一种是利用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.

Demo12: Common chunk (源码)

利用webpack.optimize.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.js') ] }

Demo13: Vendor chunk (源码)

利用ebpack.optimize.CommonsChunkPlugin,你能够把第三方库抽离出来

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

If you want a module available as variable in every module, such as making $ and jQuery available in every module without writing require("jquery"). You should use ProvidePlugin (官方文档).

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

插件会执行两次这个方法,第一次将公共的第三方代码抽离移到vendor的块中,这个过程以前也讲过会将运行时runtime也转移到vendor块中,第二次执行则是将运行时runtime抽离出来转移到manifest块中。这步操做解决了缓存问题。
这样处理,最后会生成3个打包文件chunk,app.js是业务代码,vendor则是公共的第三方代码,manifest.js则是运行时。

Demo14: Exposing global variables (源码)

webpack能够不处理应用的某些依赖库,使用externals配置后,依旧能够在代码中经过CMD、AMD或者window/global全局的方式访问。若是你想引入一些全局变量, 可是不想被加载处理, 你能够在 webpack.config.js 使用 externals 模块 (官方文档).
有时咱们但愿咱们经过script引入的库,如用CDN的方式引入的jquery,咱们在使用时,依旧用require的方式来使用,可是却不但愿webpack将它又编译进文件中。


例子, 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' } };

如今, 你能够require data 做为模块化引入进来使用. 可是其实是一个全局变量

// main.jsx var data = require('data'); var React = require('react'); var ReactDOM = require('react-dom'); ReactDOM.render( <h1>{data}</h1>, document.body );

Demo15: 热模块替换/热更新 (源码)

Hot Module Replacement (HMR) exchanges, adds, or removes modules while an application is running without a page reload.

经过webpack-dev-server.你可使用2中方式 来进行热模块替换

(1) Specify --hot and --inline on the command line

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

参数的意思:

  • --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.

  • 添加 new webpack.HotModuleReplacementPlugin() to the plugins 模块
  • 添加 webpack/hot/dev-server 和 webpack-dev-server/client?http://localhost:8080 to the entry 模块

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, '.') }] } };

启动服务

$ webpack-dev-server

访问 http://localhost:8080, 你能够在浏览器上看到 'Hello World' .

不要关闭服务.打开终端找到 App.js, 同时修改 'Hello World' 为 'Hello Webpack'. 保存后,你就能够在浏览器上看到数据更新了

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>

Demo16: React router例子 (源码)

利用webpack作的例子 React-router's 官方例子.

Let's imagine a little app with a dashboard, inbox, and calendar.

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

参照文档

License

MIT

相关文章
相关标签/搜索