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-demo.git
# Windows
$ git clone https://github.com/holidaying/webpack-demo.git
:
$ cd webpack-demo
$ npm install复制代码
接下来就能够进行demo演示了.html
$ cd demo01
$ webpack-dev-server复制代码
用浏览器访问 http://127.0.0.1:8080.前端
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"
},
// ...
}复制代码
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复制代码
多个入口文件,实用于多个页面的应用
// 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'
}
};复制代码
经过使用不一样的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.js
, module.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']
}
}
]
}复制代码
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>复制代码
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">复制代码
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
全局的.
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>")复制代码
这个例子须要加载三个插件
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 能够为你作这些事.
你能够利用环境变量来控制特定代码的输出
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复制代码
对于大型项目,把全部代码编译到一个文件并非有效的, 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
)的块。
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
.
利用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')
]
}复制代码
利用webpack.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则是运行时。
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
);复制代码
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>复制代码
利用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复制代码
全文参考阮老师的教程