# webpack-demo
**Repository Path**: rainzhai/webpack-demo
## Basic Information
- **Project Name**: webpack-demo
- **Description**: 根据阮老师的教程,敲了一遍。
- **Primary Language**: JavaScript
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2022-01-24
- **Last Updated**: 2024-11-24
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
16个demo,webpack+react搭配使用
首先教大家2个新技能
* 1.按照正常github地址情况下,你的github本身不能访问目录。
* 例如要访问vue-demo下的vueCpu文件夹:https://github.com/holidaying/vue-demo/vueCpu(显示404)但是在目录上加上tree/master/:https://github.com/holidaying/vue-demo/tree/master/vueCpu (master是分支名)就可以访问。
* 2.github目录的制作
* 明确一个问题。一个标题就是一个目录名称
* 写法\[xx\]\(#题目名称\)#不能少
* 题目名称的写法规则:abc demo-> abc-demo,Abc-Demo->abc-demo。会忽略:和()即就是题目中所有可见字符的空格均用-连接,中、英文空格要分开,中文空格对应中文-。并且全为小写
## 步骤
首先,install [Webpack](https://www.npmjs.com/package/webpack) 和 [webpack-dev-server](https://www.npmjs.com/package/webpack-dev-server).
```命令行
$ 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演示了.
```命令行
$ 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的工作方式是:在一个配置文件中,指明对某些文件进行类似编译,组合,压缩等任务的具体步骤,这个工具之后可以自动替你完成这些任务。
[更多信息](http://webpack.github.io/docs/what-is-webpack.html).
```命令行
$ webpack main.js bundle.js
```
它的配置文件是 `webpack.config.js`.
```javascript
// webpack.config.js
module.exports = {
entry: './main.js',
output: {
filename: 'bundle.js'
}
};
```
有了`webpack.config.js`,你可以不带参数使用webpack
```命令行
$ webpack
```
一些命令行选项你应该知道。
- `webpack` – 构建文件
- `webpack -p` – 发布
- `webpack --watch` – 监听项目
- `webpack -d` – 包含 source maps方便调试
- `webpack --colors` – 让打包界面更好看
去构建你的项目, 你可以把启动项写进package.json
```javascript
// package.json
{
// ...
"scripts": {
"dev": "webpack-dev-server --devtool eval --progress --colors",
"deploy": "NODE_ENV=production webpack -p"
},
// ...
}
```
## 目录
1. [单文件入口](#demo01-单文件入口-源码)
1. [多文件入口](#demo02-多文件入口-源码)
1. [Babel-loader](#demo03-babel-loader-源码)
1. [CSS-loader](#demo04-css-loader-源码)
1. [Image loader](#demo05-image-loader-源码)
1. [CSS Module](#demo06-css-module-源码)
1. [UglifyJs Plugin插件](#demo07-uglifyjs-plugin-源码)
1. [HTML Webpack Plugin and Open Browser Webpack Plugin](#demo08-html-webpack-plugin-and-open-browser-webpack-plugin-源码)
1. [Environment flags环境变量](#demo09-设置环境变量-源码)
1. [Code splitting代码分割](#demo10-code-splitting-源码)
1. [Code splitting with bundle-loader](#通过bundle-loader进行代码分裂-源码)
1. [Common chunk提取公共文件](#demo12-common-chunk-源码)
1. [Vendor chunk提取公共的第三方代码](#demo13-vendor-chunk-源码)
1. [externals全局变量](#demo14-exposing_global-variables-源码)
1. [热模块替代/热更新](#demo15-热模块替换-源码)
1. [React router](#demo16-react-router例子-源码)
## Demo01: 单文件入口 ([源码](https://github.com/holidaying/webpack-demos/tree/master/demo01))
Webpack会入口文件进行打包成bundle.js.
例子, `main.js` 是单文件入口.
```javascript
// main.js
document.write('
Hello World
');
```
index.html
```html
```
Webpack follows `webpack.config.js` to build `bundle.js`.
```javascript
// webpack.config.js
module.exports = {
entry: './main.js',
output: {
filename: 'bundle.js'
}
};
```
启动服务, 访问 http://127.0.0.1:8080 .
```bash
$ webpack-dev-server
```
## Demo02: 多文件入口 ([源码](https://github.com/holidaying/webpack-demos/tree/master/demo02))
多个入口文件,实用于多个页面的应用
```javascript
// main1.js
document.write('Hello World
');
// main2.js
document.write('Hello Webpack
');
```
index.html
```html
```
webpack.config.js
```javascript
module.exports = {
entry: {
bundle1: './main1.js',
bundle2: './main2.js'
},
output: {
filename: '[name].js'
}
};
```
## Demo03: Babel-loader ([源码](https://github.com/holidaying/webpack-demos/tree/master/demo03))
通过使用不同的loader,webpack通过调用外部的脚本或工具可以对各种各样的格式的文件进行处理([更多信息](http://webpack.github.io/docs/using-loaders.html)). 例如, [Babel-loader](https://www.npmjs.com/package/babel-loader) Babel其实是一个编译JavaScript的平台可以将 JSX/ES6 文件转换成浏览器可以识别的js文件. 官方文档[loaders](http://webpack.github.io/docs/list-of-loaders.html).
`main.jsx` is a JSX 文件.
```javascript
const React = require('react');
const ReactDOM = require('react-dom');
ReactDOM.render(
Hello, world!
,
document.querySelector('#wrapper')
);
```
index.html
```html
```
webpack.config.js
```javascript
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.js`, `module.loaders` 区域是用来分配loader的. 像上面的代码片段使用了 `babel-loader` 需要安装插件 [babel-preset-es2015](https://www.npmjs.com/package/babel-preset-es2015) 和 [babel-preset-react](https://www.npmjs.com/package/babel-preset-react) to 编译成 ES6 and React. 可以用query配置参数
```javascript
module: {
loaders: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: 'babel',
query: {
presets: ['es2015', 'react']
}
}
]
}
```
## Demo04: CSS-loader ([源码](https://github.com/holidaying/webpack-demos/tree/master/demo04))
Webpack 允许你在js文件中require CSS , 通过 CSS-loader来预处理css文件.
main.js
```javascript
require('./app.css');
```
app.css
```css
body {
background-color: blue;
}
```
index.html
```html
Hello World
```
webpack.config.js
```javascript
module.exports = {
entry: './main.js',
output: {
filename: 'bundle.js'
},
module: {
loaders:[
{ test: /\.css$/, loader: 'style-loader!css-loader' },
]
}
};
```
但是,你需要使用2中loaders来转换CSS 文件. 第一个是 [CSS-loader](https://www.npmjs.com/package/css-loader) 来读取CSS文件, 另外一个是[Style-loader](https://www.npmjs.com/package/style-loader) 是将style样式插入到html中。 中间用!连接
启动服务后, `index.html` 有内部样式.
```html
```
## Demo05: Image loader ([源码](https://github.com/holidaying/webpack-demos/tree/master/demo05))
Webpack 允许你在js文件中require图片 , 通过 url-loader和file-loader来预处理图片文件.
main.js
```javascript
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
```
webpack.config.js
```javascript
module.exports = {
entry: './main.js',
output: {
filename: 'bundle.js'
},
module: {
loaders:[
{ test: /\.(png|jpg)$/, loader: 'url-loader?limit=8192' }
]
}
};
```
[url-loader](https://www.npmjs.com/package/url-loader) 转换图片文件. 如果图片的大小小于 8192 bytes,它将会转成base64位的地址; 相反, 它就是普通地址.
参数前是用?连接的
启动服务后, `small.png` and `big.png` 将会有一下的地址.
```html
```
## Demo06: CSS Module ([源码](https://github.com/holidaying/webpack-demos/tree/master/demo06))
`css-loader?modules` (the query parameter modules) enables the [CSS Modules](https://github.com/css-modules/css-modules) spec.
CSS Module可以开启全局变量和局部变量,:global(...)表示全局变量,可以在全局中使用样式([更多信息](https://css-modules.github.io/webpack-demo/))
index.html
```html
Hello World
Hello Webpack
```
app.css
```css
.h1 {
color:red;
}
:global(.h2) {
color: blue;
}
```
main.jsx
```javascript
var React = require('react');
var ReactDOM = require('react-dom');
var style = require('./app.css');
ReactDOM.render(
Hello World
Hello Webpack
,
document.getElementById('example')
);
```
webpack.config.js
```javascript
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 ([源码](https://github.com/holidaying/webpack-demos/tree/master/demo07))
Webpack 可以去掉本身附加的东西,优化代码 [UglifyJs Plugin](http://webpack.github.io/docs/list-of-plugins.html#uglifyjsplugin) will minify output(`bundle.js`) JS codes.
main.js
```javascript
var longVariableName = 'Hello';
longVariableName += ' World';
document.write('' + longVariableName + '
');
```
index.html
```html
```
webpack.config.js
```javascript
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` 将会压缩如下.
```javascript
var o="Hello";o+=" World",document.write(""+o+"
")
```
## Demo08: HTML Webpack Plugin and Open Browser Webpack Plugin ([源码](https://github.com/holidaying/webpack-demos/tree/master/demo08))
这个例子需要加载三个插件
[html-webpack-plugin](https://github.com/ampedandwired/html-webpack-plugin) 创建 `index.html` ,[open-browser-webpack-plugin](https://github.com/baldore/open-browser-webpack-plugin) 打开浏览器
main.js
```javascript
document.write('Hello World
');
```
webpack.config.js
```javascript
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: 设置环境变量 ([源码](https://github.com/holidaying/webpack-demos/tree/master/demo09))
你可以利用环境变量来控制特定代码的输出
main.js
```javascript
document.write('Hello World
');
if (__DEV__) {
document.write(new Date());
}
```
index.html
```html
```
webpack.config.js
```javascript
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 ([源码](https://github.com/holidaying/webpack-demos/tree/master/demo10))
对于大型项目,把所有代码编译到一个文件并不是有效的, 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 来定义一个分割的点. ([官方文档](http://webpack.github.io/docs/code-splitting.html))
```javascript
// main.js
require.ensure(['./a'], function(require) {
var content = require('./a');
document.open();
document.write('' + content + '
');
document.close();
});
```
`require.ensure` 告诉 Webpack `./a.js` 应该从 `bundle.js` 中分离成一个单独的块
```javascript
// 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
```
webpack.config.js
```javascript
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进行代码分裂 ([源码](https://github.com/holidaying/webpack-demos/tree/master/demo11))
dem10是一种,另一种是利用[bundle-loader](https://www.npmjs.com/package/bundle-loader).
```javascript
// 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('' + file + '
');
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 ([源码](https://github.com/holidaying/webpack-demos/tree/master/demo12))
利用webpack.optimize.CommonsChunkPlugin,你可以共通的组件,代码块分离出来
```javascript
// main1.jsx
var React = require('react');
var ReactDOM = require('react-dom');
ReactDOM.render(
Hello World
,
document.getElementById('a')
);
// main2.jsx
var React = require('react');
var ReactDOM = require('react-dom');
ReactDOM.render(
Hello Webpack
,
document.getElementById('b')
);
```
index.html
```html
```
webpack.config.js
```javascript
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 ([源码](https://github.com/holidaying/webpack-demos/tree/master/demo13))
利用webpack.optimize.CommonsChunkPlugin,你可以把第三方库抽离出来
main.js
```javascript
var $ = require('jquery');
$('h1').text('Hello World');
```
index.html
```html
```
webpack.config.js
```javascript
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` ([官方文档](http://webpack.github.io/docs/shimming-modules.html)).
```javascript
// 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 ([源码](https://github.com/holidaying/webpack-demos/tree/master/demo14))
webpack可以不处理应用的某些依赖库,使用externals配置后,依旧可以在代码中通过CMD、AMD或者window/global全局的方式访问。如果你想引入一些全局变量, 但是不想被加载处理, 你可以在 `webpack.config.js` 使用 `externals` 模块 ([官方文档](http://webpack.github.io/docs/library-and-externals.html)).
有时我们希望我们通过script引入的库,如用CDN的方式引入的jquery,我们在使用时,依旧用require的方式来使用,但是却不希望webpack将它又编译进文件中。
例子, `data.js`.
```javascript
var data = 'Hello World';
```
We can expose `data` as a global variable.
```javascript
// 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` 作为模块化引入进来使用. 但是实际上是一个全局变量
```javascript
// main.jsx
var data = require('data');
var React = require('react');
var ReactDOM = require('react-dom');
ReactDOM.render(
{data}
,
document.body
);
```
## Demo15: 热模块替换 ([源码](https://github.com/holidaying/webpack-demos/tree/master/demo15))
[Hot Module Replacement](https://github.com/webpack/docs/wiki/hot-module-replacement-with-webpack) (HMR) exchanges, adds, or removes modules while an application is running **without a page reload**.
通过webpack-dev-server.你可以使用[2中方式](http://webpack.github.io/docs/webpack-dev-server.html#hot-module-replacement) 来进行热模块替换
(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` 如下所示.
```javascript
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
```javascript
import React, { Component } from 'react';
export default class App extends Component {
render() {
return (
Hello World
);
}
}
```
index.js
```javascript
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(, document.getElementById('root'));
```
index.html
```html
```
## Demo16: React router例子 ([源码](https://github.com/holidaying/webpack-demos/tree/master/demo16))
利用webpack做的例子 [React-router](https://github.com/rackt/react-router/blob/0.13.x/docs/guides/overview.md)'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
```
## 参照文档
- [Webpack docs](http://webpack.github.io/docs/)
- [webpack-howto](https://github.com/petehunt/webpack-howto), by Pete Hunt
- [Diving into Webpack](https://web-design-weekly.com/2014/09/24/diving-webpack/), by Web Design Weekly
- [Webpack and React is awesome](http://www.christianalfoni.com/articles/2014_12_13_Webpack-and-react-is-awesome), by Christian Alfoni
- [Browserify vs Webpack](https://medium.com/@housecor/browserify-vs-webpack-b3d7ca08a0a9), by Cory House
- [React Webpack cookbook](https://christianalfoni.github.io/react-webpack-cookbook/index.html), by Christian Alfoni
## License
MIT