blog
blog copied to clipboard
webpack3使用说明
webpack 3
入门命令
随后会用webpack-dev-server替代 基本构建
webpack src/app.js dist/app.bundle.js
开发环境实时构建
webpack --watch
生产环境中构建
webpack -p
其他
- webpack -d – 包含资源地图
- webpack --colors - 让编译的输出内容带有颜色
html-webpack-plugin
自动生成html文件,指定模板,添加hash,mini
$ npm install html-webpack-plugin --save-dev
var HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/app.js',
output: {
path: __dirname + '/dist',
filename: 'app.bundle.js'
},
plugins: [new HtmlWebpackPlugin({
template: './src/index.html',
filename: 'index.html',
minify: {
collapseWhitespace: true,
},
hash: true,
})]
};
css-loader
$ npm install --save-dev css-loader style-loader
module: {
rules: [
{
test: /\.css$/,
use: [ 'style-loader', 'css-loader' ]
}
]
}
- sass-loader
$ npm install sass-loader node-sass --save-dev
# 安装(中间可能要下载二进制包,要耐心等待)
import css from './app.scss';
rules: [
{
test: /\.scss$/,
use: [ 'style-loader', 'css-loader', 'sass-loader' ]
}
- extract-text-webpack-plugin
用 extract-text-webpack-plugin 把 CSS 分离成文件
有时候我们要把 SASS 或 CSS 处理好后,放到一个 CSS 文件中,用这个插件就可以实现。
$ npm install --save-dev extract-text-webpack-plugin
webpack-dev-server
# 先全局安装
$ npm install -g [email protected]
$ npm install [email protected] --save-dev
$ npm install webpack-cli -D
自动打开,切换端口号
module.exports = {
entry: './src/app.js',
...
devServer: {
port: 9000,
open: true
},
...
};
然后运行命令:
$ webpack-dev-server
webpack 和 babel 配置 react 开发环境
3.在 webpack 使用 babel-loader
最后我们需要在 webpack 中使用一个 loader 来转化 react 的代码。 首先,安装。
$ npm install --save-dev babel-loader
var HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {
entry: './src/app.js',
...
module: {
rules: [
{
test: /\.scss$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
//resolve-url-loader may be chained before sass-loader if necessary
use: ['css-loader', 'sass-loader']
})
},
// 这两行是处理 react 相关的内容
{ test: /\.js$/, loader: 'babel-loader', exclude: /node_modules/ },
{ test: /\.jsx$/, loader: 'babel-loader', exclude: /node_modules/ }
]
}
};
4. 写 react 组件
src/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Hello World</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
src/app.js
import css from './app.scss';
import React from 'react';
import ReactDOM from 'react-dom';
import Root from './Root';
ReactDOM.render(
<Root></Root>,
document.getElementById('root')
);
src/Root.js
import React from 'react';
export default class Root extends React.Component {
render() {
return (
<div style={{textAlign: 'center'}}>
<h1>Hello World</h1>
</div>);
}
}
用 clean-webpack-plugin 来清除文件
生产环境每次执行npm run build
都会在dist文件目录生成新的app.bundle.d01ae8858971a17f8ed2.js
,再多运行几次,生成的带 hash 的 app.bundle.js 文件就会很多。
这些带 hash 的 app.bundle.js 只有最新的才有用,其他的都没用,我们要在 build 之前把它们全清空:
$ npm i clean-webpack-plugin --save-dev
webpack.config.js
const path = require('path')
...
const CleanWebpackPlugin = require('clean-webpack-plugin');
let pathsToClean = [
'dist',
]
module.exports = {
entry: {
"app.bundle": './src/app.js'
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].[chunkhash].js'
},
...
plugins: [
new CleanWebpackPlugin(pathsToClean),
...
new ExtractTextPlugin('style.css')
],
...
};
现在运行 npm run build 试试,只有下面的文件:
dist
├── app.bundle.0e380cea371d050137cd.js
├── index.html
└── style.css
配置多个 HTML 文件
module.exports = {
entry: {
"app.bundle": './src/app.js',
// 这行是新增的。
"contact": './src/contact.js'
},
...
plugins: [
new CleanWebpackPlugin(pathsToClean),
new HtmlWebpackPlugin({
template: './src/index.html',
filename: 'index.html',
minify: {
collapseWhitespace: true,
},
hash: true,
// 这行是新增的。
excludeChunks: ['contact']
}),
new HtmlWebpackPlugin({
template: './src/contact.html',
filename: 'contact.html',
minify: {
collapseWhitespace: true,
},
hash: true,
// 这行是新增的。
chunks: ['contact']
}),
new ExtractTextPlugin('style.css')
],
...
};
上面的 excludeChunks 指的是不包含, chunks 代表的是包含。
使用 pug (jade) 作为 HTML 的模板
pug,nodejs的html模板
npm install --save-dev pug pug-html-loader raw-loader
src/index.pug
doctype html
html(lang="en")
head
title= pageTitle
script(type='text/javascript').
if (foo) bar(1 + 5)
body
h1 Pug - node template engine
#root
#container.col
if youAreUsingPug
p You are amazing
else
p Get on it!
p.
Pug is a terse and simple templating language with a
strong focus on performance and powerful features.
webpack.config.js
module.exports = {
...
plugins: [
...
new HtmlWebpackPlugin({
template: './src/index.pug',
...
}),
...
],
module: {
rules: [
...
{ test: /\.pug$/, loader: ['raw-loader', 'pug-html-loader'] }
]
}
};
我们来试试 pug 的 include 功能,就是可以包含子模板。
...
body
include includes/header.pug
...
src/includes/header.pug
h1 from header pug file
目录结构是这样的:
src
├── Root.js
├── app.js
├── app.scss
├── contact.html
├── contact.js
├── includes
│ └── header.pug
└── index.pug
如何使用模块热替换 HMR 来处理 CSS
1.启用 HMR
webpack.config.js
devServer: {
port: 9000,
open: true,
}
改成下面这样:
devServer: {
port: 9000,
open: true,
hot: true
}
webpack.config.js
...
const webpack = require('webpack');
...
module.exports = {
entry: {
"app.bundle": './src/app.js',
"contact": './src/contact.js'
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].[chunkhash].js'
},
devServer: {
port: 9000,
open: true,
hot: true
},
plugins: [
new CleanWebpackPlugin(pathsToClean),
...
// 这两行是新增的
new webpack.NamedModulesPlugin(),
new webpack.HotModuleReplacementPlugin()
],
...
};
报错!!!文件名还不能用 chunkhash 了,它说要用 hash 来代替 chunkhash。
chunkhash是每个文件都使用不同的hash值
filename: '[name].[chunkhash].js'
hash指每个文件使用相同的hash值
filename: '[name].[hash].js'
2.处理 extract-text-webpack-plugin
现在你试一下改变 src/app.scss 的内容,你会发现页面不动了,你无论怎么改,页面都不会改变,也不会刷新。
之前我们是用 extract-text-webpack-plugin 这个插件来处理 CSS 的,在用 HMR 的时候要先把它关闭一下。
用一个参数 disable: true 就可以关闭掉。
webpack.config.js
new ExtractTextPlugin("style.css")
变成
new ExtractTextPlugin({
filename: 'style.css',
disable: true
}),
然后把处理 scss 文件的 loader 部分变成类似下面这样:
...
test: /\.scss$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
//resolve-url-loader may be chained before sass-loader if necessary
use: ['css-loader', 'sass-loader']
})
...
变成
...
test: /\.scss$/,
use: ['style-loader', 'css-loader', 'sass-loader']
...
再试试,能够生效。
为什么要关闭呢这个插件呢?
其实想想也能知道,在开发环境下,用不用 extract-text-webpack-plugin 这个插件,意义不大,你把 css 变不变成一个文件,关系不大,开发环境只要能调效,效果能够看到就可以,但是生产环境需要这个插件,我们总不能开发环境不使用这个插件,也导致生产环境也不使用吧?
那如何解决这个问题呢?也就是说让生产环境使用这个插件,而开发环境不使用.
生产环境 vs 开发环境
要让生产环境使用 extract-text-webpack-plugin 这个插件,而开发环境不使用,如何做到呢?
其实原理很简单,只要能区分出哪个是开发环境,哪个是生产环境就可以,只要判断是生产环境的时候就用,不是的话...
1. 增加环境变量
首先来看一下之前的开发环境和生产环境分别使用的编译命令:
webpack.config.js
"scripts": {
"dev": "webpack-dev-server",
"prod": "webpack -p"
},
分别是开发环境使用的 npm run dev 命令和生产环境使用的 npm run prod 命令。
我们把它改成下面这样:
"scripts": {
"dev": "webpack-dev-server",
"prod": "NODE_ENV=production webpack -p"
},
开发环境的部分不变,生产环境的加了一个环境变量:
NODE_ENV=production
很简单,NODE_ENV 是变量名,而 production 是 NODE_ENV 是这个变量的值,这些都不是固定的,你可以改成你想要的任意内容,只要能引用到就行了。
那么我们如何来使用这个变量呢?
2.使用环境变量
要引用我们之前创建的环境变量,也蛮简单的。
在 webpack.config.js 文件中:
var isProd = process.env.NODE_ENV === 'production'; // true or false
process.env.NODE_ENV 就能得到之前设置的变量,如果运行的是 npm run prod,那么 process.env.NODE_ENV为true
上一节,我们有类似下面这样的两段关于 extract-text-webpack-plugin 这个插件的代码。
new ExtractTextPlugin({
filename: 'style.css',
disable: false
}),
test: /\.scss$/,
use: ['style-loader', 'css-loader', 'sass-loader']
我们把 webpack.config.js 中的代码更改如下:
...
// 线上线下切换 css-loder
var isProd = process.env.NODE_ENV === 'production'; // true or false
var cssDev = ['style-loader', 'css-loader', 'sass-loader'];
var cssProd = ExtractTextPlugin.extract({
fallback: 'style-loader',
//resolve-url-loader may be chained before sass-loader if necessary
use: ['css-loader', 'sass-loader']
})
var cssConfig = isProd ? cssProd : cssDev;
module.exports = {
...
plugins: [
...
new ExtractTextPlugin({
filename: 'style.css',
disable: !isProd
}),
...
],
module: {
rules: [
{
test: /\.scss$/,
use: cssConfig
},
...
]
}
};
只要能区别出不同的环境,使用不同的配置内容就可以了。
现在就可以放心地使用 npm run dev 和 npm run prod 命令了,再也不用临时关掉一些插件了。
3.window平台使用
windows平台:不能直接使用NODE_ENV, 步骤如下:
1.npm install cross-env --save-dev
2.命令改为 "prod": "cross-env NODE_ENV=production webpack -p"
如何打包图片
src/app.scss
body {
background: url('./images/logo.png') 0 0 no-repeat;
...
}
然后 npm run dev,你会发现类似下面的错误: 只要找到适合的 loader 来处理扩展名为 png 的图片文件即可。
1.file-loader
安装
$ npm install --save-dev file-loader
2. file-loader 的参数
其实,file-loader 是可以带参数的,例如下面这样:
test: /\.(gif|png|jpe?g|svg)$/i,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'images/'
}
},
/\.(gif|png|jpe?g|svg)$/i
表示可以处理好多图片的格式,毕竟不只是 png 才是图片,别的扩展名的文件也可能是图片嘛。
[name]
代表文件名,[ext]
代表文件扩展名,outputPath
是输出的路径。
3.解析 html 代码里面 img 的标签
忘了一个重要的地方,之前我们是在 CSS 里引用图片作为背景的,但是,我们经常是在 html 直接使用 src 标签
例如下面这样:
<img src="./images/money-bag.svg" alt="" height=50>
src/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<img src="./images/money-bag.svg" alt="" height=50>
</body>
</html>
然而结果是这样的:404了,文件找不到,没有成功。
其实缺少了一个在 html 代码里处理 img 标签的 loader。
这个 loader 是 html-loader
官方对它的定义是这样的:
Exports HTML as string. HTML is minimized when the compiler demands.
大概意思是说,把 html 变成导出成字符串的过程中,还能进行压缩处理(minimized)。
现在我们来加上这个 loader。
先安装。
$ npm install --save-dev html-loader
...
{
test: /\.(gif|png|jpe?g|svg)$/i,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'images/'
}
},
]
},
// 下面几行才是 html-loader 的配置内容
{
test: /\.html$/,
use: [ {
loader: 'html-loader',
options: {
minimize: true
}
}],
}
...
再试试发现就可以了。
4. 压缩图片
有时候图片太大,我们输出到生产环境的时候,希望可以让图片文件的体积小点,webpack 也可以轻易办到,就是自动压缩图片,然后生产环境拿到的图片就会很小。
还是用一个插件,这个插件叫 image-webpack-loader。
这个插件主要是来压缩图片文件的。
安装。
$ npm install image-webpack-loader --save-dev
webpack.config.js
{
test: /\.(gif|png|jpe?g|svg)$/i,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'images/'
}
},
{
loader: 'image-webpack-loader',
options: {
bypassOnDebug: true,
}
}
]
},
{
test: /\.html$/,
use: [ {
loader: 'html-loader',
options: {
minimize: true
}
}],
}
源文件的图片大小情况是这样的:
$ ls -lh src/images
total 256
-rw-r--r--@ 1 hfpp2012 staff 112K Nov 3 23:10 logo.png
-rw-r--r--@ 1 hfpp2012 staff 11K Dec 4 16:32 money-bag.svg
而压缩后(npm run prod):
$ ls -lh dist/images
total 96
-rw-r--r-- 1 hfpp2012 staff 33K Dec 4 21:34 logo.png
-rw-r--r-- 1 hfpp2012 staff 8.5K Dec 4 21:34 money-bag.svg
由上面的对比可知,压缩后体积减少了一些。
当然这个插件,肯定还有更多的用法,具体查看 readme 文档吧。
参考
- https://www.rails365.net/playlists/webpack-3-ling-ji-chu-ru-men-shi-pin-jiao-cheng
- https://github.com/ruanyf/webpack-demos
- https://github.com/meishadevs/webpack-demos/blob/master/README.md
补充
- https://www.jianshu.com/p/c0bec50ec385