目录
解决webpack-cli和webpack-dev-server版本冲突问题
模块转换器Loader、插件Plugins、optimization属性
webpack介绍
一个前端资源加载/打包工具。它将根据模块的依赖关系进行静态分析,然后将这些模块按照指定的规则生成对应的静态资源(把一堆的css文件和js文件放在一个总的入口文件,通过require引入,剩下的事情webpack会处理,包括所有模块的前后依赖关系,打包、压缩、合并成一个js文件,公共代码抽离成一个js文件、某些自己指定的js单独打包,模块可以是css/js/imsge/font等等)。
下面是webpack包含的一些模块。
使用方法
首先使用命令行全局安装webpack、webpack-cli、webpack-dev-server,其中webpack-cli需要指定版本号,因为默认安装的最新是4点几的版本和webpack-dev-server最新3点几的版本冲突。以下命令行代码都是在当前文件夹下运行,-D表示下载为本地项目依赖和-save-dev相同,然后npm install和yarn add相同都是下载文件
命令行:npm install webpack webpack-cli@3.3.12 webpack-dev-server -g安装全局webpack命令。
已安装了最新版本的可以通过下面方法解决。
解决webpack-cli和webpack-dev-server版本冲突问题
- npm i webpack-cli@3.3.12 -D
-
将webpack.config.js中"start"修改如下:
"scripts": {
"build": "node_modules/.bin/webpack --config webpack.config.js",
"start": "webpack serve --config webpack.config.js --open "
}
构建基本框架
在项目文件夹(取名不要为webpack)下创建src、dist、config文件夹,然后通过npm init -y创建package.js文件。然后在dist文件夹下创建index.html(主网页代码),在src文件夹下创建index.js文件,再次安装npm install webpack webpack-cli@3.3.12 webpack-dev-server -D(因为配置文件需要使用到require等语句导入webpack中的模块)。
打包
webpack4点几提供的新打包命令,当需要加载css、图片(加载插件和使用loaders等)等时需要使用webpack.config.js打包。
打包模式
在命令行中输入webpack --mode=development (打包模式为开发者环境)或webpack --mode=production(打包模式为生产者环境,经过压缩了,不会打包一些未使用的代码),最后在dist的文件夹下会生成main.js文件。还有一种是webpack -- mode none,不会经过任何外部处理。
使用webpack.config.js打包
紧接构建基本框架后,并在src文件夹下创建main.js,在config文件下创建webpack.config.js。
命令行中运行webpack --config=config/webpack.config.js(当使用webpack-dev-server.js文件时也可以输入webpack-dev-server --config=config/webpack.dev.js指定位置)指定配置文件位置(默认webpack.config.js是和package.json文件同级),此时便按照webpack.config.js中的配置打包文件。
命令行输入webpack会在dist文件夹下生成main-bundle.js,
命令行输入webpack-dev-serve便可以在网页上打开http://localhost:8080/访问到index.html文件,而index.html文件便可以通过引入main-bundle.js引入index.js和main.js。
参数含义如下:
entry:入口通过数组包裹多个入口文件名(此时会将数组中的多个文件打包成一个文件,要想打包输出多个文件,可给entry对象添加属性index:['./src/main.js'],这时便会多生成一个打包文件index-bundle.js)
详细介绍
mode:指定默认的打包模式,可以为development和production或none,
output:设置输出文件。
- filename:出口文件名[name]代表入口文件的main,生成的文件名为main-bundle.js(该文件包含所有js文件,在index.html中便只需要导入该文件),
- path:输出的路径。path.resolve()会返回将参数进行拼接后的路径名(若字符以 / 开头,不会拼接到前面的路径;若以 ../ 开头,拼接前面一个参数的路径,该参数不含最后一节路径;若以 ./ 开头或者没有符号 则拼接前面路径)。__dirname代表当前文件所在文件夹的路径(不包含文件名)。
- publicPath:以根目录的方式表示的路径,如:dist/或者是绝对路径,不应该是相对路径。在代码中引入js文件的路径为“publicPath+静态资源“,例如'/'时,在index.html中引入main-bundle.js就需要通过'/main-bundle.js'或'main-bundle.js';而为'/js'时,就需要通过'/js/main-bundle.js'引入。
webpack本地服务器
集成自动编译和自动刷新浏览器等功能。配置webpack-dev-server后使用命令行webpack-dev-server运行。
devServer:设置本地服务器。
- contentBase:设置http://localhost:8080/访问的基础路径为dist文件。即直接访问indexl.html(未设置的话http://localhost:8080/会打开项目的目录)。
- overlay:设置为true可以使错误信息不仅在命令行中显示,还会在页面中显示。
- port:本地的端口默认为8080。
- open:是否自动打开网页。
解决CORS跨域请求配置
- proxy: 设置代理解决CORS跨域问题
const path = require('path')
module.exports = {
entry: {
main: ['./src/main.js','./src/index.js']
},
mode: 'development',
output: {
filename: '[name]-bundle.js',
path: path.resolve(__dirname, 'dist'),
publicPath:'dist/'
},
devServer:{
contentBase: 'dist',
overlay: true,
port:8080,
open:true,
proxy: {
'/api': {
// http://localhost:8080/api/users => https://api.github.com/api/users
target: 'https://api.github.com',
// http://localhost:8080/api/users => https://api.github.com/users
pathRewrite: { '^/api': '' },
// 使用//api.github.com/替换localhost:8080请求GitHub的主机名
changeOrigin: true
}
}
},
}
输出文件名Hash
一般部署服务器时都会启用静态资源缓存,这样可以提升文件响应速度,但当过期时间过短会无明显作用,而过期时间过长,当应用发生更新,重新部署过后无法及时更新到客户端,可以通过采用hash文件名,当更新时文件名发生改变,会产生新的请求而不是走缓存。
通常使用chunkhash解决缓存问题。
hash
通过在output: { filename: '[name]-[hash:18].bundle.js'}、new MiniCSSExtractPlugin({filename:'[name]-[hash:18].bundle.css'})输出的文件名中添加红色部分,其中18代表产生的hash码长度。
每次打包的所有文件hash值是一样的,当有一个文件修改,所有文件的hash值都会被修改。
chunkhash
示例:output: { filename: '[name]-[chunkhash:18].bundle.js'}
相同[name]名的hash值相同。当有一个文件修改时,该文件的关联文件的hash值都会改变。
contenthash
示例:output: { filename: '[name]-[contenthash:18].bundle.js'}
每个文件hash值都不相同。当有一个文件修改时,该文件的关联文件的hash值都会改变
简化webpack命令行
修改package.json中的script标签,如下图添加start和build。这时npm start命令便等于webpack-dev-server --config=config/webpack.dev.js。
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start":"webpack-dev-server --config=config/webpack.dev.js",
"build":"webpack --config=config/webpack.dev.js"
}
属性提示
在webpack导出的module.exports对象上配置属性时想要有属性的提示,在前面补充下面这句即可。
/**@type {import('webpack').Configuration} */
@type是jsdoc特性
import('webpack').Configuration是typescript特性
引入模块(jquery)
在命令行输入npm install jquery -D,然后在main.js中通过const $=require('jquery'),之后再main.js中便可以通过$符号来使用jQery函数。
支持import函数动态导入
ES6 let注意点、解构(重命名、默认值、解构给已有变量、多层解构)、模块化(注意点、导入导出语法)、对象属性扩展写法_YF-SOD的博客-CSDN博客_let重命名
魔法注释(分包)
可以在import中添加注释让import导入的文件打包的时候单独分出一个文件进行打包。例如下图中会生成单独six-five.bundle.js文件
import(/* webpackChunkName: 'six' */ './five.js').then(v=>{})
模块转换器Loader、插件Plugins、optimization属性
包括自定loader和自定义插件plugin
https://blog.csdn.net/AIWWY/article/details/128586032
plugin链接
loader链接
HMR模块热替换
应用运行过程中实时替换某个模块,应用运行状态信息不会改变(如果网页自动刷新会使网页上内容消失)。
可以通过命令行或配置config中属性开启HMR。
- 方法一:通过webpack-dev-server --hot运行模块热替换。
- 方法二:通过config.js文件下配置,devServer下hot属性设置为true,在plugins中引入webpack的内置插件。
const webpack = require('webpack') const path = require('path') module.exports = { entry: { main: ['./src/main.js', './src/index.js'] }, mode: 'development', output: { filename: '[name]-bundle.js', path: path.resolve(__dirname, 'dist'), publicPath: 'dist/' }, devServer: { hot: true, }, module: { rules: [ ] }, plugins: [new webpack.HotModuleReplacementPlugin()] }
注意这些只能热替换css文件,js文件更新还是会刷新。
热替换手动处理js模块
在main.js中添加代码,此时当index.js的文件更新时,会只执行后面的函数而不进行刷新页面,从而实现热替换。
module.hot.accept('./index.js',() => {
//更新后执行的内容
})
热替换手动处理图片
import background from './yes.png
const img = new Image()
img.src = background
module.hot.accept('./yes.png',() => {
// 图片更新后替换图片
img.src = background
})
不同环境下配置
方法一:
函数导出
可以将webpack.config.js文件中的导出对象改为一个函数,该函数返回的是配置的对象,例如下面当命令行运行webpack --env production时,才会设置if中的内容。
module.exports = (env, args) => {
const config = {
entry: {
main: ['./src/main.js', './src/index.js']
},
output: {
filename: '[name]-bundle.js',
path: path.resolve(__dirname, 'dist'),
publicPath: 'dist/'
},
module: {
rules: [
]
},
plugins: []
}
if (env === 'production') {
config.mode = 'production'
config.devtool = false
config.plugins = [
...config.plugins,
new CleanWebpackPlugin(),
new CopyWebpackPlugin()
]
}
return config
};
方法二:
拆分多个配置文件
注意安装webpack-merge模块,命令行输入npm install webpack-merge -D,meige()中可以传入多个对象,会将多个参数合并成一个对象,和Object.assign不同的是plugins属性不会覆盖,而是将plugins数组中的值添加到公有配置plugins数组中的值合并。
在config文件夹下配置下面3个文件
- webpack.commom.js(公用配置)
将之前webpack.config.js的内容全部复制过去,去除devServer和mode属性.
- webpack.dev.js(开发环境的配置)
const common = require('./webpack.common')
const {merge} = require('webpack-merge');
module.exports = merge(common, {
mode: 'development',
devServer: {
contentBase: 'dist',
overlay: true,
port: 8080,
open: true
}
})
- webpack.prod.js(生产环境配置)
const common = require('./webpack.common')
const merge = require('webpack-merge')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin');
const { webpack } = require('webpack');
module.exports = merge(common, {
mode: 'production',
plugins: [
new CleanWebpackPlugin(),
new CopyWebpackPlugin(['public'])
]
})
通过webpack --config=config/webpack.dev.js打包为开发环境的,通过webpack --config=config/webpack.prod.js打包为生产者环境。
Source Map
用于映射源文件和编译后文件的关系,通过.map文件可以将编译后的文件转换为源文件。.解决了源代码与运行代码不一致的问题。
map文件中一般有以下属性:
- version:版本号
- sources: 数组,包括源文件名
- names: 数组,包括源文件中用到的变量名
- mappings:base64/vlq编码的字符串,记录转换编译之后文件到源文件之间的关系。
例如当在html中引入jquery-3.4.1.min.js文件时,想在控制台中的Sources中可以调试jquery的源码(非压缩的)。在min.js文件中最后添加下面这句话,在网页中就会自动请求.map文件将其对应到源文件,此时
//# sourceMappingURL=jquery-3.4.1.min.map
webpack配置source map
const path = require('path')
module.exports = {
entry: {
main: './src/main.js'
},
mode: 'development',
output: {
filename: '[name]-bundle.js',
path: path.resolve(__dirname, 'dist'),
publicPath: 'dist/'
},
devtool: 'source-map',
module: {
rules: [
]
},
plugins: []
}
添加devtool:'source-map'属性即可,webpack编译后的main-bundle.js最下面会添加
//# sourceMappingURL=main-bundle.js.map
这样在控制台的source中可以调试源main.js代码。
开发环境通常cheap-module-eval-source-map(可以调试未经过loader处理的源代码,首次打包速度慢无所谓,重写打包相对较快) 。
生产环境通常选择none,因为sourcemap会暴露源代码。次选为nosources-source-map。