一 环境搭建
webpack其实就是一个JavaScript应用程序的静态模块打包器。
webpack会将项目的资源文件当成一个一个模块,模块之间会有依赖关系,
webpack将会对这些有依赖关系的文件进行处理,让浏览器能够识别,
最后将应用程序需要的每个模块打包成一个或者多个bundle
1.安装node
node官网地址: https://nodejs.org/zh-cn/
2.创建package.json文件
npm init
3.安装webpack
本地安装:(推荐)
npm install --save-dev webpack
npm install --save-dev webpack-cli
全局安装:
npm install --global webpack webpack-cli
4.打包
默认配置
entry:"src/index.js"
output:"dist/main.js"
package.json文件下添加scripts,配置打包模式
{
"scripts":{
"dev":"webpack --mode development",
"prod":"webpack --mode production"
}
}
npm run dev
npm run prod
二 基础配置webpack.config.js
1.新建文件 webpack.config.js
2.配置入口entry和output
(1)path指文件打包后的存放路径
(2)path.resolve()方法将路径或路径片段的序列处理成绝对路径
(3)__dirname 表示当前文件所在的目录的绝对路径
(4)filename是打包后文件的名称
示例代码:
const path = require('path');
module.exports = {
entry:'./public/index.js',
output:{
path:path.resolve(__dirname,'build'),
filename:"bundle.js"
}
}
示例代码2:
const path = require('path');
module.exports = {
// 多文件单出口
// entry:['./public/index.js','./public/index2.js'],
// output:{
// path:path.resolve(__dirname,'build'),
// filename:"bundle.js"
// }
//多入口多出口
entry:{
pageOne: './public/pageOne/index.js',
pageTwo: './public/pageTwo/index.js',
pageThree: './public/pageThree/index.js'
},
output:{
path:path.resolve(__dirname,'build'),
filename:"[name].js"
}
}
3.配置webpack-dev-server
npm install --save-dev webpack-dev-server
配置webpack.config.js文件
devServer:{
contentBase:"./build",
host:"localhost",
port:8080,
open:true //自动打开页面
}
配置package.json
"scripts": {
"start": "webpack-dev-server --mode development"
}
在build文件夹下新建index.html文件,在html中引入bundle.js
npm run start
二 loader加载组件
1.加载css
npm install style-loader css-loader --save-dev
在webpack.config.js文件里配置module中的rules
module:{
rules:[
{
test:/.css$/,
use:['style-loader','css-loader']
}
]
}
创建index.css文件并import进index.js文件中
import './index.css';
2.加载编译less和sass
安装less-loader和less 和 安装sass-loader和node-sass
npm install less-loader less --save-dev
npm install sass-loader node-sass --save-dev
在webpack.config.js文件里配置module中的rules
module:{
rules:[
{
test:/.less$/,
use:['style-loader','css-loader','less-loader']
},
{
test:/.scss$/,
use:['style-loader','css-loader','sass-loader']
}
]
}
3.使用PostCSS添加浏览器前缀
npm install --save-dev postcss-loader autoprefixer
需要和autoprefixer一起用,在webpack.config.js文件里配置module中的rules
module:{
rules:[
{
test:/.css$/,
use:['style-loader','css-loader',{
loader:'postcss-loader',
options:{
plugins:[require("autoprefixer")()]
}
}]
}
]
}
4 文件处理
npm install --save-dev file-loader
图片module中的rules
module:{
rules:[
{
test:/.(png|jpg|gif|jpeg)$/,
use:[{
loader:'file-loader',
options:{
name:'[hash]wangou.jpg',
outputPath:'./img'
}
}]
}
]
}
配置options:
name:为你的文件配置自定义文件名模板(默认值[hash].[ext])
context:配置自定义文件的上下文,默认为 webpack.config.js
publicPath:为你的文件配置自定义 public 发布目录
outputPath:为你的文件配置自定义 output 输出目录
[ext]:资源扩展名
[name]:资源的基本名称
[path]:资源相对于 context的路径
[hash]:内容的哈希值
字体module中的rules
module:{
rules:[
{
test:/.(ttf|woff|woff2|eot|svg)$/,
use:[{
loader:'file-loader',
options:{
outputPath:'font/'
}
}]
}
]
}
js库module中的rules
以jquery库为例子
1)本地导入
const webpack = require('webpack');
module.exports = {
entry:'./public/index.js',
resolve:{
alias:{
jQuery: path.resolve(__dirname,"public/js/jquery.min.js")
}
},
plugins:[
new webpack.ProvidePlugin({
jQuery:"jQuery"
})
]
}
2)npm安装模块
安装jquery库:
npm install jquery --save-dev
直接在js里import引入
import $ from 'jquery'
5 HTML中引入图片
cnpm install --save-dev html-loader
module中的rules
{
test:/.(html)$/,
option:{
attrs:['img:src', 'img:data-src']
}
}
6.babel编译ES6
module:{
rules:[
{
test:/.js$/,
exclude:/node_modules/,
use:'babel-loader'
}
]
},
webpack 插件
1.生成HTML
npm install html-webpack-plugin --save-dev
module中的rules
const HtmlWebpackPlugin = require('html-webpack-plugin');
plugins:[
new HtmlWebpackPlugin({
template:"./public/index.html",
filename:"webpack.html",
minify:{
minimize:true,
removeComments:true,
removeAttributeQuotes:true,
collapseWhitespace:true,
minifyCSS:true,
minifyJS:true,
removeEmptyElements:true
},
hash:true
})
]
2.提取分离css
npm install --save-dev mini-css-extract-plugin
module中的rules
const MiniCssExtractPlugin = require("mini-css-extract-plugin")
module:{
rules:[
{
test:/.css$/,
use:[MiniCssExtractPlugin.loader,'css-loader',{
loader:'postcss-loader',
options:{
plugins:[require("autoprefixer")()]
}
}]
}
]
},
plugins:[
new MiniCssExtractPlugin({
filename:"./css/[name].css"
})
]
3 压缩css及优化css结构
npm install --save-dev optimize-css-assets-webpack-plugin
module中的rules
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
plugins:[
new OptimizeCSSAssetsPlugin({
assetNameRegExp:/.css$/g,
cssProcessor:require('cssnano'),
cssProcessorPluginOptions:{
preset:['default',{discardComments:{removeAll:true}}]
},
canPrint:true
})
]
4copy静态文件
module中的rules
const CopyWebpackPlugin = require('copy-webpack-plugin');
plugins:[
new CopyWebpackPlugin([
{
from:__dirname+'/public/assets',
to:__dirname+'/build/assets'
}
])
]
5清除垃圾文件
npm install --save-dev clean-webpack-plugin
module中的rules
const CleanWebpackPlugin = require('clean-webpack-plugin');
plugins:[
new CleanWebpackPlugin({
dry: false
}),
]
6 SourceMap 调试代码
1)js调试
devtool:"source-map"
2)css调试
调试css时需要将压缩css的插件注释掉(optimize-css-assets-webpack-plugin)
module:{
rules:[
{
test:/.css$/,
use:[{
loader:'css-loader',
options:{
source:true
}
}]
}
]
},
7模块热替换
devServer:{
contentBase:'./build', //设置服务器访问的基本目录
host:'localhost', //服务器的ip地址
port:8080, //端口
open:true, //自动打开页面
hot:true,
hotOnly:true
},
plugins:[
new webpack.NamedModulesPlugin(),
new webpack.HotModuleReplacementPlugin(),
]
entry文件js
if(module.hot){
module.hot.accept()
}
8区分生产环境和开发环境
npm install --save-dev webpack-merge
将webpack.config.js拆分为三个文件,分别是webpack.common.conf.js、webpack.dev.conf.js和webpack.prod.conf.js。
webpack.common.conf.js是放一些我们公用的配置,比如入口entry、出口output、常用loader以及插件等。
webpack.dev.conf.js是在开发环境上的配置,比如devServer配置、模块热替换等方便开发的配置
webpack.prod.conf.js是在生产环境上的配置,比如提取分离css、压缩css和js等
webpack.common.conf.js
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
module.exports = {
entry:'./public/index.js',
output:{
path:path.resolve(__dirname,'../build'),
filename:"bundle.js"
},
module:{
rules:[
{
test:/.css$/,
use:['style-loader','css-loader',{
loader:'postcss-loader',
options:{
plugins:[require("autoprefixer")()],
sourceMap:true
}
}]
},
{
test:/.less$/,
use:['style-loader','css-loader','less-loader']
},
{
test:/.scss$/,
use:['style-loader','css-loader','sass-loader']
},
{
test:/.(png|jpg|gif|jpeg)$/,
use:[{
loader:'file-loader',
options:{
name:'[hash]wangou.jpg',
outputPath:'./img'
}
}]
},
{
test:/.(ttf|woff|woff2|eot|svg)$/,
use:[{
loader:'file-loader',
options:{
outputPath:'font/'
}
}]
},
{
test:/.js$/,
exclude:/node_modules/,
use:'babel-loader'
},
{
test:/.(html)$/,
use:{
loader:'html-loader',
options: {
attrs: ['img:src','img:data-src']
}
}
}
]
},
resolve:{
alias:{
jQuery: path.resolve(__dirname,"../public/js/jquery.min.js")
}
},
plugins:[
new CleanWebpackPlugin(['build'],{
root:path.resolve(__dirname,'../')
}),
new webpack.ProvidePlugin({
jQuery:"jQuery"
}),
new HtmlWebpackPlugin({
template:"./public/index.html",
filename:"webpack.html",
minify:{
minimize:true,
removeComments:true,
removeAttributeQuotes:true,
collapseWhitespace:true,
minifyCSS:true,
minifyJS:true,
removeEmptyElements:true
},
hash:true
}),
// 分离css
// new ExtractTextPlugin("./css/[name].css")
new MiniCssExtractPlugin({
filename:"./css/[name].css"
}),
]
}
webpack.dev.conf.js
const webpack = require('webpack');
const merge = require('webpack-merge');
const common = require('./webpack.common.conf.js');
module.exports = merge(common,{
devtool:'cheap-module-eval-source-map',
devServer:{
contentBase:'./build', //设置服务器访问的基本目录
host:'localhost', //服务器的ip地址
port:8080, //端口
open:true, //自动打开页面
hot:true,
hotOnly:true
},
plugins:[
new webpack.NamedModulesPlugin(),
new webpack.HotModuleReplacementPlugin()
]
})
webpack.prod.conf.js
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const common = require('./webpack.common.conf.js');
const merge = require('webpack-merge');
const path = require('path');
module.exports = merge(common,{
devtool:'source-map',
plugins:[
new CopyWebpackPlugin([
{
from:path.resolve(__dirname,'../public/assets'),
to:path.resolve(__dirname,'../build/assets')
}
])
]
})
配置文件package.json
"scripts": {
"dev": "webpack --mode development --config ./config/webpack.dev.conf.js",
"build": "webpack --mode production --config ./config/webpack.prod.conf.js",
"start": "webpack-dev-server --mode development --config ./config/webpack.dev.conf.js"
},
四 优化打包的速度
1.减少文件搜索范围
1)优化resolve.extensions配置
在导入语句没带文件后缀时,Webpack 会自动带上后缀后去尝试询问文件是否存在。
在配置 resolve.extensions 时你需要遵守以下几点,以做到尽可能的优化构建性能:
后缀尝试列表要尽可能的小,不要把项目中不可能存在的情况写到后缀尝试列表中。
频率出现最高的文件后缀要优先放在最前面,以做到尽快的退出寻找过程。
在源码中写导入语句时,要尽可能的带上后缀,从而可以避免寻找过程。例如在你确定的情况下把 require('./data') 写成 require('./data.json') 。
2)优化 resolve.modules 配置
resolve.modules 用于配置 Webpack 去哪些目录下寻找第三方模块。
resolve.modules 的默认值是 ['node_modules'],会采用向上递归搜索的方式查找
(3)优化resolve.alias配置
resolve.alias 配置项通过别名来把原导入路径映射成一个新的导入路径。
(4)缩小文件匹配范围
Include:需要处理的文件的位置
Exclude:排除掉不需要处理的文件的位置
2.设置noParse
防止 webpack 解析那些任何与给定正则表达式相匹配的文件。忽略的文件中不应该含有 import, require, define 的调用,或任何其他导入机制。忽略大型的 library 可以提高构建性能。比如jquery、elementUI等库
3.给babel-loader设置缓存
babel-loader 提供了 cacheDirectory特定选项(默认 false):设置时,给定的目录将用于缓存加载器的结果。
4.使用happyPack
HappyPack的基本原理:在webpack构建过程中,我们需要使用Loader对js,css,图片,字体等文件做转换操作,并且转换的文件数据量也是非常大的,且这些转换操作不能并发处理文件,而是需要一个个文件进行处理,HappyPack的基本原理是将这部分任务分解到多个子进程中去并行处理,子进程处理完成后把结果发送到主进程中,从而减少总的构建时间。