本文从代码压缩、代码拆分、样式分离等三个方面对生产环境的代码进行了优化。只是最简单的一些配置,若是真正运用到项目中,还须要根据项目添加更多配置。css
本文讲述的是如何对生产环境下的代码进行压缩,若是还不是太了解 Webpack 的朋友,能够先看一下个人上一篇文章:从零开始搭建一个 Webpack 开发环境配置(附 Demo)html
本文项目代码位置:源码地址webpack
首先编写一个项目,初始化 npm,而后 在本地安装 webpack,接着安装 webpack-cli(此工具用于在命令行中运行 webpack):git
$ mkdir webpack-prod-demo
$ cd webpack-prod-demo
$ npm init -y
$ npm install webpack webpack-cli --save-dev
复制代码
projectgithub
webpack-prod-demo
|- package.json
|- /public
|- index.html
|- /src
|- index.js
|- index.css
复制代码
pubic/index.htmlweb
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Webpack 生产环境配置</title>
</head>
<body>
</body>
</html>
复制代码
index.jsnpm
import './index.css';
function component() {
var element = document.createElement('div');
element.innerHTML = 'Hello World';
return element;
}
document.body.appendChild(component());
复制代码
index.cssjson
div {
color: blue;
text-align: center;
}
复制代码
package.json浏览器
{
"name": "webpack-prod-demo",
"version": "1.0.0",
"description": "",
"private": true,
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack --config webpack.config.js"
},
"keywords": [],
"author": "",
"license": "ISC"
}
复制代码
在根目录下新建 webpack.config.js 文件,并进行基本配置bash
安装插件
# 安装 babel-loader
$ npm install babel-core babel-loader@7 --save-dev
# 安装 babel presets
$ npm install babel-preset-env babel-preset-stage-0 --save-dev
# 安装 babel plugins
$ npm install babel-plugin-transform-class-properties babel-plugin-transform-runtime babel-runtime --save-dev
# 安装其他所需 loader
$ npm install css-loader style-loader file-loader csv-loader xml-loader html-loader markdown-loader --save-dev
# 安装 webpack 插件
$ npm install clean-webpack-plugin html-webpack-plugin friendly-errors-webpack-plugin --save-dev
复制代码
配置 webpack.config.js:
webpack.config.js
const path = require('path');
const HTMLWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const FriendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin');
module.exports = {
mode: 'development',
devtool: 'hidden-source-map',
entry: './src/index.js',
output: {
filename: '[name]-[hash:8].js',
path: path.resolve(__dirname, 'dist')
},
plugins: [
new HTMLWebpackPlugin({
// 用于生成的HTML文档的标题
title: 'Webpack 生产环境配置',
// webpack 生成模板的路径
template: './public/index.html'
}),
// 用法:new CleanWebpackPlugin(paths [, {options}])
new CleanWebpackPlugin(['dist']),
// 在命令行进行友好提示
new FriendlyErrorsWebpackPlugin()
],
module: {
rules: [
{
test: /\.js/,
include: path.resolve(__dirname, 'src'),
loader: 'babel-loader?cacheDirectory'
},
// 解析 css
{
test: /\.css$/,
include: path.resolve(__dirname, 'src'),
use: [
'style-loader',
// 还能够给 loader 添加一些配置
{
loader: 'css-loader',
options: {
// 开启 sourceMop
sourceMap: true
}
}
]
},
// 解析图片资源
{
test: /\.(png|svg|jpg|gif)$/,
use: [
'file-loader'
]
},
// 解析 字体
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
use: [
'file-loader'
]
},
// 解析数据资源
{
test: /\.(csv|tsv)$/,
use: [
'csv-loader'
]
},
// 解析数据资源
{
test: /\.xml$/,
use: [
'xml-loader'
]
},
// 解析 MakeDown 文件
{
test: /\.md$/,
use: [
"html-loader",
"markdown-loader"
]
}
]
}
}
复制代码
在项目根目录下建立 .babelrc 文件
.babelrc
{
"presets": ["env", "stage-0"],
"plugins": [
"transform-runtime",
"transform-class-properties"
]
}
复制代码
在命令行运行指令:
$ npm run build
复制代码
此时在浏览器打开 dist 文件夹下的 html 文件,页面上正常显示 蓝色居中的 Hello World
查看此时 dist 文件大小:
production
webpack.config.js
...
module.exports = {
mode: 'production'
...
}
复制代码
在命令行运行指令:
$ npm run build
复制代码
此时在浏览器打开 dist 文件夹下的 html 文件,页面上仍是可以正常显示 蓝色居中的 Hello World
查看此时 dist 文件大小:
安装须要用到的插件:
# 安装压缩 js、 css 代码的插件
$ npm install uglifyjs-webpack-plugin optimize-css-assets-webpack-plugin --save-dev
# 安装提取 css 的插件
$ npm install mini-css-extract-plugin --save-dev
复制代码
webpack.config.js
...;
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
module.exports = {
...,
optimization: {
// 打包压缩js/css文件
minimizer: [
new UglifyJsPlugin({
uglifyOptions: {
compress: {
// 在UglifyJs删除没有用到的代码时不输出警告
warnings: false,
// 删除全部的 `console` 语句,能够兼容ie浏览器
drop_console: true,
// 内嵌定义了可是只用到一次的变量
collapse_vars: true,
// 提取出出现屡次可是没有定义成变量去引用的静态值
reduce_vars: true,
},
output: {
// 最紧凑的输出
beautify: false,
// 删除全部的注释
comments: false,
}
}
}),
new OptimizeCSSAssetsPlugin({
cssProcessorOptions: {
safe: true
}
})
]
}
}
复制代码
uglifyjs-webpack-plugin 更多配置请参考:插件文档。
optimize-css-assets-webpack-plugin 更多配置请参考:插件文档。
注意: MiniCssExtractPlugin.loader 和 style-loader 一块儿使用可能出现问题。因此下面我将 style-loader 去掉了。
webpack.config.js
...;
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
...
plugins: [
...,
// 打包后提取出css文件
new MiniCssExtractPlugin({
filename: '[name].[contenthash:8].css',
chunkFilename: '[name].[contenthash:8].chunk.css'
})
],
module: [
rules: [
...,
// 解析 css
{
test: /\.css$/,
include: path.resolve(__dirname, 'src'),
use: [
{
loader: MiniCssExtractPlugin.loader
},
// 还能够给 loader 添加一些配置
{
loader: 'css-loader',
options: {
// 开启 sourceMop
sourceMap: true
}
}
]
},
...
]
]
}
复制代码
mini-css-extract-plugin 更多配置请参考:插件文档。
webpack.config.js
...;
module.exports = {
...,
optimization: {
// 打包压缩js/css文件
minimizer: [
...
],
splitChunks: {
chunks: 'all'
}
}
}
复制代码
splitChunks 更多配置请参考:官方文档。
在开发网页的时候,通常都会有多套运行环境,例如:
为了尽量的复用代码,在构建的过程当中须要根据目标代码要运行的环境而输出不一样的代码,咱们须要一套机制在源码中去区分环境。能够经过 Webpack 内置的 DefinePlugin 插件进行环境的区分。
区分环境的缘由: 不少第三方库中也作了环境区分的优化
注意: NODE_ENV 和 'production' 两个值是社区的约定,一般使用这条判断语句在区分开发环境和线上环境。
配置:
webpack.config.js
...
module.exports = {
...,
plugins: [
...,
// 区分环境
new webpack.DefinePlugin({
// 定义 NODE_ENV 环境变量为 production
'process.env': {
NODE_ENV: JSON.stringify('production')
}
})
],
...
}
复制代码
在命令行运行指令:
$ npm run build
复制代码
此时在浏览器打开 dist 文件夹下的 html 文件,页面上仍能正常显示 蓝色居中的 Hello World
查看此时 dist 文件大小:
其他文件基本未进行修改。在此将 webpack.config.js 代码贴出来
webpack.config.js
const path = require('path');
const HTMLWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const FriendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
mode: 'production',
devtool: 'hidden-source-map',
entry: './src/index.js',
output: {
filename: '[name]-[hash:8].js',
path: path.resolve(__dirname, 'dist')
},
plugins: [
new HTMLWebpackPlugin({
// 用于生成的HTML文档的标题
title: 'Webpack 开发环境配置',
// webpack 生成模板的路径
template: './public/index.html'
}),
// 用法:new CleanWebpackPlugin(paths [, {options}])
new CleanWebpackPlugin(['dist']),
// 在命令行进行友好提示
new FriendlyErrorsWebpackPlugin(),
// 打包后提取出css文件
new MiniCssExtractPlugin({
filename: '[name].[contenthash:8].css',
chunkFilename: '[name].[contenthash:8].chunk.css'
}),
// 区分环境
new webpack.DefinePlugin({
// 定义 NODE_ENV 环境变量为 production
'process.env': {
NODE_ENV: JSON.stringify('production')
}
})
],
module: {
rules: [
{
test: /\.js/,
include: path.resolve(__dirname, 'src'),
loader: 'babel-loader?cacheDirectory'
},
// 解析 css
{
test: /\.css$/,
include: path.resolve(__dirname, 'src'),
use: [
{
loader: MiniCssExtractPlugin.loader
},
// 还能够给 loader 添加一些配置
{
loader: 'css-loader',
options: {
// 开启 sourceMop
sourceMap: true
}
}
]
},
// 解析图片资源
{
test: /\.(png|svg|jpg|gif)$/,
use: [
'file-loader'
]
},
// 解析 字体
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
use: [
'file-loader'
]
},
// 解析数据资源
{
test: /\.(csv|tsv)$/,
use: [
'csv-loader'
]
},
// 解析数据资源
{
test: /\.xml$/,
use: [
'xml-loader'
]
},
// 解析 MakeDown 文件
{
test: /\.md$/,
use: [
"html-loader",
"markdown-loader"
]
}
]
},
optimization: {
// 打包压缩js/css文件
minimizer: [
new UglifyJsPlugin({
uglifyOptions: {
compress: {
// 在UglifyJs删除没有用到的代码时不输出警告
warnings: false,
// 删除全部的 `console` 语句,能够兼容ie浏览器
drop_console: true,
// 内嵌定义了可是只用到一次的变量
collapse_vars: true,
// 提取出出现屡次可是没有定义成变量去引用的静态值
reduce_vars: true,
},
output: {
// 最紧凑的输出
beautify: false,
// 删除全部的注释
comments: false,
}
}
}),
new OptimizeCSSAssetsPlugin({
cssProcessorOptions: {
safe: true
}
})
],
splitChunks: {
chunks: 'all'
}
}
}
复制代码
经过三次打包的对比,能够看到:
目前这个项目一个 js 文件,代码量不多,可是仍是能够看到优化的效果的。若是项目更大的话,优化的效果也会更明显。固然,须要的配置可能更多了。
本文只是对于生产环境下代码打包的简单优化,在项目实战的过程当中,可能会须要更多的配置。其实不管看多少教程,其实里面的配置都不必定可以知足自身的要求。在开发的过程当中,仍是须要本身根据需求进行配置。
其实 Webpack 的学习并不难,根据官网的说明和指南,其实基本都会使用。难的是各类 loader、plugin 自身的配置。这些都须要去到 loader 和 plugin 的网站上深刻研究才能够。因此想要更好的进行 webpack 配置,仍是须要多多留意最新技术的出现,多搜集有用的插件和配置。聚沙成塔,慢慢的就能配置出更好的项目脚手架(目前这也是个人目标)。