webpack作用
- 打包(把多个文件打包成一个js文件,减少服务器的压力、减少请求)
- 转化 (比如 less、sass、ts,需要loader转化器)
- 优化(SPA页面,前端项目复杂度增加,webpack优化)
webpack构成
- 入口 entry
- 出口 output
- loaders 转化器
- plugins 插件
- devServer 开发服务器
- mode
安装webpack
npm install webpack webpack-cli -g
验证:webpack -v
扩展:npm
安装:
npm install jquery --save-dev
可以写成:
npm i jquery -D
npm install jquery --save
可以写成:
npm i jquery -S
卸载
npm unistall jquery --save-dev
可以写成:
npm un jquery -D
webpack配置
- 1:默认 webpack.config.js
套路:就是由这几部分组成
module.exports = {
entry: { }, // 入口配置
output: { }, // 出口配置
module: { }, // 模块规则,module.rules,用来配置各种loader
plugins: [ ], // 插件 数组
devServer: { } // 服务器
};
实例:最简单测试
const path = require('path'); // 这是node内置的模块
console.log(path.resolve(__dirname, 'dist')); // path.resolve表示合并,__dirname也是node内置的,表示该项目的根目录,这里就表示: C:\E\教程\webpack\demo1,所以合并的结果就是:C:\E\教程\webpack\demo1\dist
module.exports = {
entry: {
a: './src/index.js'
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
}
};
注意:除了使用默认的webpack.config.js配置文件外,还可以自己指定相应的配置文件:
方法1:webpack --config webpack.config.dev.js
方法2:利用node,在package.json中的scripts配置
如:
"scripts": {
"build": "webpack --config webpack.config.dev.js"
},
在cmd直接运行:node run build
多入口(多文件),插件 html-webpack-plugin
- 基础
webpack配置:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: { // 多入口 key-value
index: './src/index.js',
index2: './src/index2.js',
},
output: { // 多出口,出口的名字,通过内部定义好的变量 [name] 拿到出口文件的 key
path: path.resolve(__dirname, 'dist'),
filename: '[name].bundle.js'
},
mode: 'production',
plugins: [
new HtmlWebpackPlugin({
title: 'i love u',
hash: true,
template: './src/index.html',
minify: {
collapseWhitespace: true,
removeAttributeQuotes: true
}
})
]
};
说明:html-webpack-plugin
1:html-webpack-plugin依赖 webpack、webpack-cli模块
2:安装:npm i --save-dev html-webpack-plugin
3:引入:const HtmlWebpackPlugin = require('html-webpack-plugin');
4:使用:plugins: [
new HtmlWebpackPlugin({})
]
5:注意在配置title的时候,需要在模板中的title修改:
<%= htmlWebpackPlugin.options.title %>
- 进阶 利用html-webpack-plugin 生成多个页面,或者多个页面分别引入自己的js;这个配置使用了另一个插件clean-webpack-plugin
注意:如果使用 optimization.splitChunks 这里要注意html-webpack-plugin的chunks属性可能会影响。
配置:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const cleanWebpackPlugin = require('clean-webpack-plugin');
module.exports = {
entry: {
index: './src/index.js',
index2: './src/index2.js',
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].bundle.js'
},
mode: 'development',
plugins: [
new cleanWebpackPlugin(['dist']), // 打包之前,先清除掉之前打的包
new HtmlWebpackPlugin({ // 多个HtmlWebpackPlugin,打包生成多个页面,要指定filename
title: 'i love u',
hash: true,
template: './src/index.html',
minify: {
collapseWhitespace: true,
removeAttributeQuotes: true
},
filename: 'index3.html', // 打完包的名字,自己决定
chunks: ['index'] // 跟入口文件的key对应,引入自己的js
}),
new HtmlWebpackPlugin({
title: 'u love i',
hash: true,
template: './src/index2.html',
minify: {
collapseWhitespace: true,
removeAttributeQuotes: true
},
filename: 'index2.html',
chunks: ['index2']
}),
]
};
说明:
1:需要打包几个文件,就配置几个new HtmlWebpackPlugin;
2:对应配置的new HtmlWebpackPlugin 可以分别配置不同的模板,通过配置 filename 来区分最后打包出来的文件名,filename值可以自己随便定义;
3:可以通过配置 chunks ,来指定这个 HtmlWebpackPlugin 的模板需要引入哪些自己的模块,这个值,是跟entry入口文件中的key对应。
4:对于clean-webpack-plugin插件,直接new cleanWebpackPlugin(['dist'])配置打包前需要清除的文件夹即可,是数组。
开发环境需要的服务:webpack-dev-server
1:安装
npm i webpack-dev-server -D
2:配置(不用require)
devServer: {
contentBase: './dist',
host: 'localhost',
port: '8888',
open: true, // 自动开发游览器
hot: true // 热更新,这里需要配置webpack内置的HotModuleReplacementPlugin插件,不然会报错
}
3:使用webpack-dev-server 打包,并不会生成文件,只会在内存里,所以看不到打包出来的文件。
4:利用package.json进行打包:
"scripts": {
"build": "webpack --config webpack.config.pro.js",
"dev": "webpack-dev-server --config webpack.config.dev.js"
},
5:完整配置文件:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const cleanWebpackPlugin = require('clean-webpack-plugin');
const webpack = require('webpack');
module.exports = {
entry: {
index: './src/index.js',
index2: './src/index2.js',
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].bundle.js'
},
mode: 'production',
plugins: [
new webpack.HotModuleReplacementPlugin, // 热更新需要引入这个插件
new cleanWebpackPlugin(['dist']), // 打包之前,先清除掉之前打的包
new HtmlWebpackPlugin({ // 多个HtmlWebpackPlugin,打包生成多个页面,要指定filename
title: 'i love u',
hash: true,
template: './src/index.html',
minify: {
collapseWhitespace: true,
removeAttributeQuotes: true
},
filename: 'index.html', // 打完包的名字,自己决定
chunks: ['index', 'index2'] // 跟入口文件的key对应,引入自己的js
}),
],
devServer: {
contentBase: './dist',
host: 'localhost',
port: '8888',
open: true, // 自动开发游览器
hot: true // 热更新,这里需要配置webpack内置的HotModuleReplacementPlugin插件,不然会报错
}
};
loaders
预先说明
- a:module中rules中的三种写法
例:
module: {
rules: [
{
test: /\.css$/,
// 注意:对于css,必须先使用css-loader,再使用style-loader
// use: ['style-loader', 'css-loader'] // 第一种写法
// loader: ['style-loader', 'css-loader'] // 第二种写法
use: [ // 第三种写法
{ loader: 'style-loader' },
{ loader: 'css-loader' }
]
}
]
},
- b:打包完上线肯定要压缩
1:方式一:利用mode
利用webpack4x 的特性,mode
生产:压缩
mode --production
开发:不压缩
mode --development
2:方式二:使用插件 uglifyjs-webpack-plugin
1:安装:npm i -D uglifyjs-webpack-plugin
2:const Uglify = require('uglifyjs-webpack-plugin');
3:new Uglify()
1:css
使用的loader:style-loader、css-loader
1:安装 npm i style-loader css-loader -D
2:配置loader:
module: {
rules: [
{
test: /\.css$/,
// 注意:对于css,必须先使用css-loader,再使用style-loader
// use: ['style-loader', 'css-loader'] // 第一种写法
// loader: ['style-loader', 'css-loader'] // 第二种写法
use: [ // 第三种写法
{ loader: 'style-loader' },
{ loader: 'css-loader' }
]
}
]
},
说明:
1:loader的加载顺序是从右往左的,所以,需要先加载css-loader,再加载style-loader:
2:这里指支持css,后面要扩展 sass、less和使用postcss
分离css:使用的插件 extract-text-webpack-plugin
1:安装:这个插件对于webpack4x的安装需要使用下个版本
npm i extract-text-webpack-plugin@next -D
2:引入:
const ExtractTextPlugin = require('extract-text-webpack-plugin');
3:使用:
new ExtractTextPlugin('css/style.css') // 分离打包后的css存放的路径
4:对css load规则进行修改配置:
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: 'css-loader',
publicPath: '../'
})
},
//对 publicPath: '../' 说明: 因为我们图片使用outputPath存放的路径为images目录,
// 而css打包后 new ExtractTextPlugin('css/style.css') 存放的目录为css/style.css,
// 所以,对于图片,style.css寻找文件时,需要往上一层找
2:图片
使用的loader:url-loader、file-loader
1:安装:npm i url-loader file-loader -D
2:配置:
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'url-loader',
options: {
limit: 70000, // 限制70kb的时候,使用base64压缩,如果大于的话,则使用路径
outputPath: 'images' // 大于70kb,图片打包存放的在images目录下
}
}
]
}
处理 less、sass和使用postcss处理前缀
- less:使用less-loader
1:安装:
npm install --save-dev less-loader less
2:配置:
{
test: /\.less$/,
use: [
{ loader: 'style-loader' },
{ loader: 'css-loader' },
{ loader: 'less-loader' },
]
},
有分离:
{ // 分离less
test: /\.less$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: ['css-loader', 'less-loader', 'postcss-loader'],
publicPath: '../'
})
},
- sass:使用sass-loader
1:安装:
npm install sass-loader node-sass webpack --save-dev
2:配置:
{
test: /\.(sass|scss)$/,
use: ['style-loader', 'css-loader', 'sass-loader']
},
分离:
{ // 分离
test: /\.(sass|scss)$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: ['css-loader', 'sass-loader'],
publicPath: '../'
})
},
- postcss:配置前缀
1:安装:
cnpm i -D postcss-loader
cnpm i -D autoprefixer // 前缀
在根目录下,新增postcss 的配置文件:postcss.config.js
postcss.config.js配置为:
module.exports = {
plugins: [
require('autoprefixer')
]
}
以css为例配置postcss:(项目中,也需要为相应的less或者sass配置)
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: ['css-loader', 'postcss-loader'],
publicPath: '../'
})
},
优化:使用插件 purifycss-webpack 消除冗余css代码
1:安装:
npm i -D purifycss-webpack purify-css
npm i -D glob // 配置全局路径需要
2:引入:
const glob = require('glob');
const PurifyCSSPlugin = require('purifycss-webpack');
3:配置:
new PurifyCSSPlugin({
// Give paths to parse for rules. These should be absolute!
paths: glob.sync(path.join(__dirname, 'src/*.html')),
})
sourceMap 关联源码
// 生产调试需要开启源码,实际生产一定要关闭
devtool: 'source-map'
babel
说明:
a:babel是用来编译js
b:可以方便的使用ES各个版本(es6、es7等)
c:jsx语法转化
1:安装:
cnpm i babel-core babel-loader babel-preset-env -D
cnpm i babel-preset-react -D // react 需要的preset
2:在根目录配置.babelrc
{
"presets": [
"env",
"react"
]
}
3:配置:
{
test: /\.(js|jsx)$/,
use: [
{
loader: 'babel-loader',
}
],
exclude: /node_modules/
}
注意,preset也可以直接在use中配置,但是,**不建议**,使用.babelrc可以方便扩展
{
test: /\.(js|jsx)$/,
use: [
{
loader: 'babel-loader',
options: {
preset: 'evn'
}
}
],
exclude: /node_modules/
}
react
1:安装:
cnpm i react react-dom -S
需要在.babelrc配置react 的preset ,所以需要安装
cnpm i babel-preset-react -D
2:在根目录配置.babelrc
{
"presets": [
"env",
"react"
]
}
webpack用到模块化
例:aa.js
const model = function () {
return "123"
}
module.exports = model;
说明:通过 module.exports中导出
webpack 中使用 require导入
const aa = require("./aa.js");
webpack4x使用json
例:
test.json:
{
"port": "8888"
}
webpack使用:
const testConfig = require("./test.json");
说明:webpack3x是需要安装json-loader,4x不需要。
使用第三方库,利用插件 ProvidePlugin
例:
1:const webpack = require('webpack');
2:
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery'
}),
说明:
1:虽然可以通过 import $ from jQuery;但是,不建议,因为只要一通过import,不管页面有无有到,都会被打包。
2:使用ProvidePlugin插件,只要使用到此库,才会被打包。
optimization.splitChunks
注意:webpack4x已经废弃 CommonsChunkPlugin
optimization: {
splitChunks: {
cacheGroups: {
vendors: {
chunks: 'initial',
name: 'jquery',
enforce: true
}
}
}
}
注意:
1:使用optimization时,注意不要给HtmlWebpackPlugin插件,配置chunks,否则,会影响。
2:optimization的上下文是在根路径,与entry、output等同级。
练习最后的webpack配置代码,参考即可
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const cleanWebpackPlugin = require('clean-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const webpack = require('webpack');
const glob = require('glob');
const PurifyCSSPlugin = require('purifycss-webpack');
const ip = require("./ip.config.js");
const jsonConfig = require("./test.json");
console.log(ip);
console.log(ip());
console.log(jsonConfig);
console.log(jsonConfig.port);
module.exports = {
entry: {
index: './src/index.js',
jquery: 'jquery'
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].bundle.js'
},
mode: 'development',
module: {
rules: [
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: ['css-loader', 'postcss-loader'],
publicPath: '../'
})
},
{ // 分离less
test: /\.less$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: ['css-loader', 'less-loader', 'postcss-loader'],
publicPath: '../'
})
},
// {
// test: /\.less$/,
// use: [
// { loader: 'style-loader' },
// { loader: 'css-loader' },
// { loader: 'less-loader' },
// ]
// },
// {
// test: /\.(sass|scss)$/,
// use: ['style-loader', 'css-loader', 'sass-loader']
// },
{ // 分离
test: /\.(sass|scss)$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: ['css-loader', 'sass-loader'],
publicPath: '../'
})
},
{
test: /\.(js|jsx)$/,
use: [
{
loader: 'babel-loader',
}
],
exclude: /node_modules/
},
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'url-loader',
options: {
limit: 70000,
outputPath: 'images'
}
}
]
}
]
},
devtool: 'source-map',
plugins: [
new webpack.HotModuleReplacementPlugin,
new cleanWebpackPlugin(['dist']), // 打包之前,先清除掉之前打的包
new HtmlWebpackPlugin({ // 多个HtmlWebpackPlugin,打包生成多个页面,要指定filename
title: 'i love u',
hash: true,
template: './src/index.html',
minify: {
collapseWhitespace: true,
removeAttributeQuotes: true
},
filename: 'index.html', // 打完包的名字,自己决定
// chunks: ['index'] // 跟入口文件的key对应,引入自己的js
}),
new ExtractTextPlugin('css/style.css'),
new PurifyCSSPlugin({
// Give paths to parse for rules. These should be absolute!
paths: glob.sync(path.join(__dirname, 'src/*.html')),
}),
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery'
}),
],
optimization: {
splitChunks: {
cacheGroups: {
vendors: {
chunks: 'initial',
name: 'jquery',
enforce: true
}
}
}
},
devServer: {
contentBase: './dist',
host: 'localhost',
port: '8888',
open: true, // 自动开发游览器
hot: true // 热更新,这里需要配置webpack内置的HotModuleReplacementPlugin插件,不然会报错
}
};
webpack-dev-server 配置跨域
headers: {'Access-Control-Allow-Origin': '*'}