本文是在请练完这16个webpack小例子基础上补充的webpack2的版本
安装
$ npm i -g webpack webpack-dev-server
配置
配置文件为 webpack.config.js
module.exports = {
entry: './main.js', // 入口文件
output: {
filename: 'bundle.js' //打包后的文件名
}
};
命令行
- webpack 构建文件
- webpack -p 发布
- webpack --watch 监听项目
- webpack -d 包含source map方便调试
- webpack --colors让打包界面更好看
在package.json中配置命令
{
// ...
"scripts": {
"dev": "webpack-dev-server --devtool eval --progress --colors",
"deploy": "NODE_ENV=production webpack -p"
},
// ...
}
使用
单文件入口
module.exports = {
entry: './main.js',
output: {
filename: 'bundle.js'
}
};
多文件入口
module.exports = {
entry: {
bundle1: './main1.js',
bundle2: './main2.js'
},
output: {
filename: '[name].js'
}
};
引用
<html>
<body>
<script src="bundle1.js"></script>
<script src="bundle2.js"></script>
</body>
</html>
loaders
某些规律
在loaders的每个对象中,
- 使用多个loader,用!连接
- 传递参数是在loader名字后面加?,多个参数用&连接
babel-loader
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 区域是用来分配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']
}
}
]
}
css-loader style-loader
先在css-loader中读取css文件,这里为main.js
注意移动在某个js文件中引入css文件
// main.js
require ('./xxx.css')
之后再style-loader中将样式插入到html中
module.exports = {
entry: './main.js',
output: {
filename: 'bundle.js'
},
module: {
loaders:[
{ test: /\.css$/, loader: 'style-loader!css-loader' },
]
}
};
image-loader
参数前是用?连接的
依然和处理css格式的文件一样,需要在main.js中require,然后用fileloader
var img1 = document.createElement("img");
img1.src = require("./small.png");
document.body.appendChild(img1);
转换为图片文件
module.exports = {
entry: './main.js',
output: {
filename: 'bundle.js'
},
module: {
loaders:[
{ test: /\.(png|jpg)$/, loader: 'url-loader?limit=8192' }
]//url-loader 转换图片文件. 如果图片的大小小于 8192 bytes,它将会转成base64位的地址; 相反, 它就是普通地址.
}
};
Module
css module
CSS Module可以开启全局变量和局部变量,:global(...)表示全局变量,可以在全局中使用样式
更多配置
: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')
);
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'
}
]
}
};
使用composes
如需要引用以下两个css文件:
style1.css
.text1{
......
color:yellow;
}
style2.css
.text2{...}
定义一个main.css供于继承并引用
.context1{
composes:text1 from "path/style1.css";
color:red; // 这里会覆盖原有样式
}
.context2{
composes:text2 from "path/style2.css";
color:blue;
}
在main.js中
import styles from './main.css';
import React, { Component } from 'react';
export default class varA extends Component {
render() {
return (
<div className={styles.context1}>
<p className={styles.context2}>Style Variant A</p>
</div>
);
}
};
css动画的处理
anime.css
@keyframes bounce {
33% { transform: translateY(-20px); }
66% { transform: translateY(0px); }
}
.bounce {
animation: bounce 1s infinite ease-in-out;
}
main.css
.bounce{
composes: bounce from 'path/anime.css'
background-color:red;
}
main.js
import styles from './main.css';
import React, { Component } from 'react';
export default class varB extends Component {
render() {
return (
<div className={styles.bounce}>
</div>
);
}
}
Plugins
UglifyJs Plugin
可以优化代码,去掉本身附加的东西,减小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 & open browser webpack plugin
html-webpack-plugin 创建 index.html,open-browser-webpack-plugin 打开浏览器
HtmlwebpackPlugin只支持node7
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'
})
]
};
环境变量
设置环境变量控制特定的代码输出路径
var webpack = require('webpack');
module.exports = function() {
return {
entry: './main.js',
output: {
filename: 'bundle.js'
},
plugins: [
new webpack.EnvironmentPlugin(['NODE_ENV', 'DEBUG'])
]
};
};
// main.js
document.write('<h1>Hello World</h1>');
if (process.env.NODE_ENV === 'production') {
console.log('Welcome to production');
}
if (process.env.NODE_ENV === 'development') {
console.log('Welcome to development'); // show
}
if (process.env.DEBUG) {
console.log('Debugging output'); // show
}
注意:先命令行执行 set NODE_ENV=development,之后再wds
code splitting
a.js
module.export="i will be compiled to 0.bundle.js"
main.js
function determinated(){
// import()中不能写入变量!!
import('./a').then((a)=>{
document.open()
document.write(`<h1>${a}</h1>`)
document.close()
}).catch((err)=>{
console.log(err)
})
}
determinated()
webpack.config.js不变,但最后编译出来的代码被分成了两个部分。
CommonsChunkPlugin
CommonsChunkPlugin是一个选择性功能,可以创建一个单独的文件(称为一个块),由多个入口点之间共享的通用模块组成。通过将公共模块与捆绑分开,生成的分块文件最初可以加载一次,并存储在高速缓存中供以后使用。这会使页面优化,因为浏览器可以快速提供来自缓存的共享代码,而不是每当访问新页面时被强制加载更大的包
// webpack.config.js
//CommonsChunkPlugins是webpack自身的方法,功能是提取两个方法共有的代码模块
var webpack = require('webpack');
var uglifyJsPlugin = webpack.optimize.UglifyJsPlugin;
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?presets[]=es2015&presets[]=react'},
]
},
plugins: [
new webpack.optimize.CommonsChunkPlugin({
name: "init'",
filename: "init.js",
}),
new uglifyJsPlugin({
compress: {
warnings: false
}
})
]
}
注意加载顺序,要把通用模块放在前面
<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>
两个bundle文件中都包含init
Vendor chunk
抽第三方库,并设置为变量,拿jquery举例。比如:
// main.js
$('h1').text('Hello World');
$('h1').css('color','red');
// webpack.config.js
var webpack = require('webpack');
module.exports = {
entry: {
app: './main.js',
vendor: ['jquery'],
},
output: {
filename: 'bundle.js'
},
plugins: [
new webpack.optimize.CommonsChunkPlugin({
name:'vendor',
filename:'vendor.js'
}),
new webpack.ProvidePlugin({
$: 'jquery',//在这里设置一个变量
jQuery: 'jquery'
})
]
};
// 省略部分代码
// 要先引入vendor.js
<script src="vendor.js"></script>
<script src="bundle.js"></script>
Exposing global variables
如果想引入某些模块,但不想被webpack预加载且依然可以通过CMD、AMD或者window/global全局的方式访问。
比如,想要全局引入data.js,但不想被编译到bundle中
// data.js
var data = 'Hello World';
// 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' },
]
},
externals: {
'data2': 'data' //data2为注册的全局变量
}
};
// main.js
var data2 = require('data2'); //直接require就可以了
var React = require('react');
var ReactDOM = require('react-dom');
var $ = require("jquery");
ReactDOM.render(
<h1>{data2}</h1>,
document.body
);
Hot Module Replacement
热更新是在应用程序运行时不进行页面重新加载的情况下交换,添加或删除模块。
亲测webpack2只要wds就可以实现热更新了,以下配置适用于wepack1
两种方法
- 命令行
$ webpack-dev-server --hot --inline
2.修改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?$/,
loaders: ['babel-loader?presets[]=es2015&presets[]=react'],
include: path.join(__dirname, '.')
}]
}
};