1、webpack安装
初始化package.json
npm init -y
安装依赖
cnpm install webpack weback-cli -D
webpack依赖webpack-cli,所以2个都要引入
2、0配置打包
在根目录下新建src文件夹,并新建index.js文件。
index.js
const str = require('./a')
console.log(str)
a.js
module.exports = '一起来学webpack'
开始打包
webpack
在根目录生成一个dist文件夹,里面有打包好的main.js文件
3、webpack基本配置打包
在根目录新建webpack.config.js,我们先配置打包配置的模式、入口、出口
const path = require('path')
module.exports = {
mode:'development',
entry: './src/index.js',
output: {
filename: "bundle.[hash:8].js", //输出文件增加hash,防止缓存。如果源文件内容未修改,hash与上一次一致
path: path.resolve(__dirname,'dist')
},
}
webpack.config.js人家为默认文件名,支持手动修改。在node-moduls中的webpack-cli/bin/config/config-yargs.js文件中可以查看该名字。
image.png现在我们把配置文件改为webpack.configmy.js。
有2种打包方式:手打打包、配置脚本打包
1、我们可以任意修改该文件名称,打包时,执行以下命令
webpack --config webpack.configmy.js[修改后的名称]
2、在package.json中配置脚本
"scripts": {
"build": "webpack --config webpack.configmy.js"
},
然后在命令行中执行 npm run build
image.png4、webpack打包出来结果分析
1、我们打开打包后的文件,不难发现,这个文件里面的其实是一个自执行函数。
2、参数modules是一个对象,该对象键为源文件的路径,值为一个函数。
3、自执行函数里面还有一个webpack_require函数,在自执行函数中调用并返回module.exports
4、首先传入的入口文件"index.js",返回值为该函数,该函数又调用webpack_require,传入的引用的a.js文件,最后a.js对应的函数返回module.export。如引用多个,同理。得到的返回结果,在入口文件获取到,并进行操作。
5、webpack-dev-server配置
安装依赖
cnpm install webpack-dev-server -D
在webpack.config.js配置相关参数
devServer: {
port:3000, // 配置指定端口
progress:true, // 配置可以看到进度调
contentBase:'./dist' // 配置指定目录下的index.html
}
在package.json 配置脚本
"scripts": {
"dev": "webpack-dev-server"
},
注意:
1、打开浏览器时, 默认在根目录寻找index.html ,如果没有index.html则会显示根目录的文件和文件夹。
如有配置,就从配置的目录寻找index.html
6、html-webpack-plugin插件使用
html-webpack-plugin插件用于开发模式下,生成html页面,并把打包后的js文件引用到html模板。
安装依赖及配置
cnpm install html-webpack-plugin -D
webpack.config.js
plugins: [
new HtmlWebpackPlugin({ // 生成html模板页面
template: "./src/index.html", // 模板路径
filename: "index.html", // 打包后的文件
minify: {
removeAttributeQuotes:true, // 打包文件html去掉引号(默认为true)
collapseWhitespace:true // 缩成一行(默认为true)
}
})
]
8、查看webpack-dev-server环境下打包生成的文件
[http://localhost:3000/webpack-dev-server](http://localhost:3000/webpack-dev-server)
image.png
9、解析scss、sass、less文件
1、解析scss、sass文件(scss是sass的升级版,用法与扩展名有区别)需要的依赖
cnpm install sass sass-loader -D
配置
{
test: /\.sass$/,
use: [
"style-loader" // 把css插入head标签
'css-loader', // 识别@import
'sass-loader'
]
},
{
test: /\.scss$/,
use: [
"style-loader",
'css-loader', // 识别@import
'sass-loader'
]
},
sass的扩展名是sass,scss的扩展名是scss
2、解析less
依赖安装
cnpm install less less-loader
配置
{
test: /\.less$/, //解析css文件
use: [
"style-loader"
'css-loader', // 识别@import
'less-loader'
]
}
注意:
1、在.css文件中通过@import引入.scss等文件会无效
10、css合并与样式添加浏览器前缀
安装依赖
cnpm install autoprefixer postcss-loader -D
配置
webpack.config.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
plugins: [
new MiniCssExtractPlugin({ // 把css处理成一个css文件
filename:'main.css'
})
],
module: {
rules: [
// loader执行顺序:从右到左,从下到上
{
test: /\.css$/, //解析css文件
use: [
MiniCssExtractPlugin.loader, // 把css 打包成一个文件
'css-loader', // 识别@import
'postcss-loader', // css自动增加浏览器前缀
]
},
{
test: /\.scss$/, //解析css文件
use: [
MiniCssExtractPlugin.loader, //合并css为一个文件
'css-loader',
'postcss-loader', // 添加前缀放在css-loader之前
'sass-loader'
]
},
]
}
在根目录新建postcss.config.js
module.exports = {
plugins: [
require('autoprefixer')
]};
要配合在package.json文件配置该文件,否则无效
package.json
"browserslist": [
"last 2 versions",
"> 1%",
"iOS 7",
"last 3 iOS versions"
],
11、压缩css、js
安装依赖
cnpm install optimize-css-assets-webpack-plugin uglifyjs-webpack-plugin -D
配置
optimization: {
minimizer: [
new UglifyJsPlugin({
cache:true,
parallel:true,
sourceMap:true
}),
new OptimizeCss() // css压缩
]
},
12、高级js(es6及以上)转为es5 babel-loader
安装插件
cnpm install babel-loader @babel/core @babel/preset-env -D
配置
module: {
rules: [
{
test: /\.js$/, //解析js(es6转es5等)
use:{
loader: "babel-loader",
options: {
presets:[
'@babel/preset-env'
]
}
},
},
]}
13、generation语法识别@babel/plugin-transform-runtime
安装插件
cnpm install @babel/plugin-transform-runtime @babel/runtime -D
配置
module: {
rules: [
{
test: /\.js$/, //解析js(es6转es5等)
use:{
loader: "babel-loader",
options: {
presets:[
'@babel/preset-env'
],
plugins:[
"@babel/plugin-transform-runtime"
]
},
},
include: path.resolve(__dirname,'src'), // 匹配src下的js文件
exclude: /node_modules/ // 排除node_modules的文件,否则会找里面的js文件
},
]}
注意:
一定要配上excelude,否则会去node_modules里面找所有的js文件
该插件主要用于这些语法
function* gen(params) {
yield 1;
}
console.log(gen().next())
14、重写高级方法@babel/polyfill
安装插件
cnpm install @babel/polyfill(不需要D)
引入
a.js
require('@babel/polyfill')
console.log('aaa'.includes('a'))
查看打包出来的文件,发现在Array.prototype中实现了includes方法。
15、js代码校验 eslint
依赖
cnpm install eslint eslint-loader
配置
{
test: /\.js/, // js代码校验
use: {
loader: "eslint-loader",
options: {
enforce:'pre', // js代码校验要在转换之前,增加enforce参
数【pre,post】
}
},
},
再把官网提供的配置文件引入到根目录
16、全局变量引入问题(变量挂载到window)
安装依赖
cnpm install expose-loader -D
比如说我们引入jquery,其他包需要引入全局的jquery($),
第一种写法:
a.js
import $ from 'expose-loader?$!jquery'
console.log(window.$)
支持 获取
第二种写法:
a.js
import $ from 'jquery'
console.log(window.$)
webpack.config.js
module: {
rules: [
{
test: require.resolve('jquery'), // 内联loader,把对象暴露出来,挂载到window
use:'expose-loader?$'
},
]}
支持¥、window.¥获取
第三种写法
webpack.config.js
plugins: [
new webpack.ProvidePlugin({
$:'jquery'
})
],
在每个页面都引入了jquery,支持$获取,不支持window.x
第四种
使用cnd
在index.html
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.js"></script>
17、图片解析
图片展示方式一般有三种:
1、在js创建imges 展示
2、在css作为background,背景图片使用
3、在html的img标签引入使用
依赖
cnpm install file-loader url-loader html-withimg-loader -D
配置
module: {
rules: [
{ // 解析html中的img
test: /\.html$/,
use:'html-withimg-loader'
},
{
test: /\.(png|jpg|gif)$/, // 解析js/css中图片的使用
use:{
loader:'url-loader',
options: {
limit:200*1024, // 小于200k,使用base64,否则显示file-loader真实图片路径
outputPath:'img/', // 图片输出到指定目录下
esModule:false // 用与解决img标签图片中src问题
}
}
},
]}
使用
1.在js
import global from './Global-Position.png'
let img = new Image()
img.src=global
document.body.appendChild(img)
2、在css
div{
width: 100px;
height: 50px;
background: url("../Global-Position.png");
}
3、在html
<img src="./Global-Position.png" alt="" style="width: 100px;height: 50px"></div>
注意:
1、在img标签引入图片,会有这样的问题
ERROR in Error: Parse Error: <img src={"default":"389a66a25c539a9fd3524d58c43e2560.png"}> <script type="text/javascript" src="bundle.js?588181ceb9662c845b90"></script></body> </html>
解决方案:
在file-loader 或者url-loader中设置esModule:false
18、打包多入口文件
// 多入口配置
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
mode:'development',
entry: {
home:'./src/firstIndex.js',
other:'./src/secondIndex.js',
},
output: {
filename: "[name].[hash].js",
path:path.resolve(__dirname,'dist')
},
plugins: [
new HtmlWebpackPlugin({
template: "./src/index.html",
filename: "home.html",
chunks: ['home'] // home.html中引入home.js,否则所有的js都会被引入
}),
new HtmlWebpackPlugin({
template: "./src/index.html",
filename: "other.html",
chunks: ['other']
}),
]
}
1、entry配置不同的入口文件路径
2、output的filename,使用【name】来区分打包输出的什么文件
3、new多个HtmlWebpackPlugin,生成多个html文件。参数要设置chunks参数需要引入的js文件名字,否则
会把所有的js都引入。
19、source-map 打包映射
(1) devtool: "source-map",
代码映射,会单独生成一隔sourcemap文件,出错了会标识当前报错的列和行。js文件很小
image.png
image.png
(2)devtool: "eval-source-map",
不会产生单独的文件,但是可以显示行和列。但是js文件比source-map打包出来的大一些
image.png
image.png
(3) devtool: "cheap-module-source-map",
不会产生列,但是是一个单独的映射文件
image.png
image.png
(4)devtool: "cheap-module-eval-source-map",
不会产生文件,集成在打包后的文件中,不会产生列
image.png
image.png
20、打包watch
webpack.config.js
watch: true,
watchOptions: {
poll: 1000, //每秒询问一次是否打包
aggregateTimeout:500, // 防抖 防止一直输入代码一直打包,页面一直刷新
ignored: /node_modules/ // 忽略监控文件
},
监听打包后文件。
21、常用小插件
1、清除插件
cnpm install cleanWebpackPlugin -D
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
plugins:[
new CleanWebpackPlugin(),
]
2、copy插件
cnpm install copy-webpack-plugin -D
const CopyWebpackPlugin = require('copy-webpack-plugin')
new CopyWebpackPlugin( [ // 报错??
{ from: 'from', to: './' },
])
3、设置版权插件
const webpack = require('webpack')
plugins:[
new webpack.BannerPlugin('make in 2020')
]
打包出来的结果前面会添加版权信息
image.png
22、跨域问题
1、前端解决跨域问题
devServer: {
proxy:{
'/api':{ // 请求路径关键字
target:'http:192.168.1.23:3000', //代理到的目标
pathReWrite:{'/api':''} // 后台接口可能没有api关键字,要移除掉
}
}
},
2、node后端解决跨域
let middle = require('webpack-dev-middleware')
let config = require('./webpack.config')
let compiler = webpack(config)
app.use(middle(compiler))
3、后端解决跨域
cnpm install cors -D
const cors = require('cors')
app.use(cors())
23、resolve
resolve: {
modules: [path.resolve('node_modules')], // 从指定寻找资源
extensions: ['.js','.css','.json','.vue'], // 寻找相同名字不同扩展名的文件顺序
mainFields: ['style','main'], // 寻找资源中package.json文件寻找相同名字的文件顺序
alias: {
bootstrap:'bootstrap/dist/css/bootstrap.css', // 资源路径别名
'@': resolve('src')
}
},
24、定义环境变量
plugins: [
new webpack.DefinePlugin({ // 设置环境变量,在页面可以直接获取DEV的值
DEV:JSON.stringify('dev'), // 输出字符串加JSON.stringify,或者多加一个双引号
FLAG:'true', // 输出boolean值
EXPORESSION:'1+1'
}),
]
webpack.config.js中配置的环境变量可以在页面中获取
webpack 优化配置
1、noParse 设置无依赖包
noParse:/jquery/, //没有依赖其他文件的包,设置可以noParse,减少打包时间
2、设置资源寻找范围
module: {
noParse:/jquery/, //没有依赖其他文件的包,设置可以noParse,减少打包时间
rules:[
{
test: /\.js$/,
exclude: /node_modules/,
include: path.resolve('src'),
use: {
loader: "babel-loader",
options: {
presets:[
'@babel/preset-env'
],
}
}
}
]
},
我们在页面使用import 引入资源的时候,默认是从node-modules开始寻找该资源,但是如果我们的资源
并不在node-module内,这样会浪费时间,所以我们可以设置一个exclude和include告诉,忽略哪里,从哪里开始寻找
3、设置忽略包
比如项目中引入了moment.js文件,里面的内容包含了所有的语言包,但是并不需要所有。webpack提供了一个IgnorePlugin插件,支持忽略某些内容,减少打包容量,然后再自己手动添加需要的语言包。
new webpack.IgnorePlugin(/\.\/locale/,/moment/)
4、多线程打包
cnpm install happypack -D
const Happypack = require('happypack')
webpack.config.js
plugins: [
new Happypack({
id:'css',
use:['style-loader','css-loader']
}),
new Happypack({
id:'js',
use:[{
loader:'babel-loader',
options: {
presets:['@babel/preset-env']
}
}]
}),
]
module: {
rules:[
{
test: /\.js$/,
exclude: /node_modules/,
include: path.resolve('src'),
use: 'Happypack/loader?id=js'
},
{
test: /\.css$/, //解析css文件
use: 'Happypack/loader?id=css'
},
{
test: /\.scss$/, //解析css文件
use: [
'css-loader',
'postcss-loader',
'sass-loader'
]
},
]
},
使用happypack插件创建需要的类型(如css、js),然后在rules中使用对应的happypack,用id来识别。
项目比较小,如果使用多线程打包可能时间返回花得多,因为线程的分配也是需要时间的。
5、抽离公共代码、第三方库
optimization: {
splitChunks: {
cacheGroups: {
common:{// 公共模块
chunks: "initial",//初始化的时候进行抽离
minSize:0,
minChunks:2,// 使用的次数
},
vendor:{// 第三方库
priority:1,
test: /node_modules/,
chunks: "initial",
minSize:0,
minChunks:2
}
}
}
},
网友评论