装置
- 全局装置
webpack
和webpack-cli
,是为了能够应用webpack
这个命令,不然你应用不了命令,当然手动增加环境变量也是能够的,部分装置是为了锁定版本,不便开发对立版本号,这里是应用了指定版本号的,也是踩了坑的,版本号不同,配置大同小异,然而,外面一个变动,你不晓得,出错了就有你好查的了。 -
自己在做开发的时候,遇到的最多的就是版本号的坑。基本上
webpack
版本号是多少,其余的关联包,根本都要在肯定范畴内,超出了范畴,就等着一堆报错吧,自己用的这个版本是本人踩过确定可用的。npm i webpack@4.46 webpack-cli-3.3.12 -g npm i webpack@4.46 webpack-cli-3.3.12 -D
- 如果不想批改一次内容,就打包一次看成果,还能够装置上面和这个包
- 而后只须要运行,
npx webpack-dev-server
或者npx webpack serve
,而后咱们再改变代码,就能立即在浏览器中看到对应的成果了 npx webpack-dev-server
不好记还长,那么在package.json
的 scripts 中配置个 dev 启动命令吧:"dev": "webpack-dev-server"
或者"dev": "webpack serve"
-
该形式就是用来实时预览的,不会打包,只会在内存中虚构打包,让你看到成果,须要打包的话还是要应用
webpack
命令打包。npm i webpack-dev-server@3.11.0
package.json 文件中的配置
// 更新于 2022/02/22
{
"name": "webpack1",
"version": "1.0.0",
"description": "","main":"index.js","scripts": {"dev":"webpack-dev-server","build":"webpack --config webpack.config.js","prod":"webpack --config webpack.prod.config.js"},"author":"",
"license": "ISC",
"devDependencies": {
"@babel/core": "^7.11.6",
"@babel/polyfill": "^7.11.5",
"@babel/preset-env": "^7.11.5",
"add-asset-html-webpack-plugin": "^5.0.1",
"babel-eslint": "^10.1.0",
"babel-loader": "^8.1.0",
"core-js": "^3.21.1",
"css-loader": "^4.3.0",
"eslint": "^7.11.0",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-loader": "^4.0.2",
"eslint-plugin-import": "^2.25.4",
"file-loader": "^6.1.0",
"html-loader": "^1.3.2",
"html-webpack-plugin": "^4.5.0",
"less": "^4.1.2",
"less-loader": "^6.0.0",
"mini-css-extract-plugin": "^1.0.0",
"optimize-css-assets-webpack-plugin": "^5.0.4",
"postcss": "^8.1.1",
"postcss-loader": "^4.0.4",
"postcss-preset-env": "^7.4.1",
"style-loader": "^2.0.0",
"url-loader": "^4.1.0",
"webpack": "^4.46.0",
"webpack-cli": "^3.3.12",
"webpack-dev-server": "^3.11.0"
},
"dependencies": {
"@babel/polyfill": "^7.11.5",
"core-js": "^3.21.1",
"jquery": "^3.6.0"
},
"browserslist": {
"development": [
">0.2%",
"not dead",
"not op_mini all"
],
"production": [
">0.2%",
"not dead",
"not op_mini all"
]
},
"eslintConfig": {
"extends": "airbnb-base",
"parser": "babel-eslint"
}
}
webpack.config.js 配置
配置中的五个外围点
-
Entry(入口)
- Entry 批示 Webpack 以哪个文件为入口终点开始打包,剖析构建外部依赖图
-
Output(输入)
- Output 批示 Webpack 打包后资源的 bundles 输入到哪里去,以及如何命名
-
Module
- Module 中的 Loader 让 Webpack 可能去解决那些非 JS 文件(webpack 自身只了解 JS,还有 JSON)
-
Plugins(插件)
- Plugins 能够用于执行范畴更广的工作,插件的范畴包含从打包优化和压缩,始终到从新定义环境中的变量等
-
Mode(模式)
-
Mode 批示 Webpack 应用相应模式的配置
- development
- production
-
配置文件具体代码
/*
webpack.config.js: webpack 的配置文件
作用:批示 webpack 干哪些活,即当你运行 webpack 指令时,会加载外面的配置
所有构建工具都是基于 NodeJS 平台运行的,所以模块化采纳的都是 commonjs
开发环境配置
*/
// 应用 resolve 用来拼接绝对路径的办法
const {resolve} = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin');
const webpack = require('webpack')
const AddAssetHtmlWebpackPlugin = require('add-asset-html-webpack-plugin')
// 设置 nodejs 环境变量
process.env.NODE_ENV = 'development'
/*
entry: 入口终点
1. string ---> './src/index.js'
- 单入口
- 打包造成一个 chunk,输入一个 bundle 文件。- 此时 chunk 的名称默认为 main
2. array ---> ['./src/index.js','./src/index2.js']
- 多入口
- 所有入口文件最终只会造成一个 chunk,输入进来只有一个 bundle 文件。- 一般来讲,只有在 HMR 性能中让 html 的热更新失效:['./src/index.js','./src/index.html']
3. object ---> {index: './src/index.js', index2:'./src/index2.js'}
- 多入口
- 有几个入口文件就造成几个 chunk,输入几个 bundle 文件,这个也是文件切割的一种模式
- 此时 chunk 的名称是 key
- 非凡用法:能够用来把两个打包成一个
{
index: ['./src/index.js','./src/add.js',
index2:'./src/index2.js'
}
*/
module.exports = {
// webpack 配置
// 入口
entry: ['./src/index.js','./src/index.html'],
// 输入
output: {
// 输入文件名
filename: 'js/[name].[hash:10].js',
// 输入门路
path: resolve(__dirname,'dist'),
// 所有资源引入的公共门路前缀:'./img/bg.png'
// publicPath: '/',
// 非入口 chunk 的名称
// chunkFilename: '',
// 整个库向外裸露的变量名, 个别只有联合 dll 才应用
// library: '[name]',
// 变量名增加到哪个上
// libraryTarget: 'window'
// libraryTarget: 'browser'
},
// loader 的配置
module: {
// 具体 loader 配置
rules: [
// JS 的语法查看:eslint eslint-loader
// 除了要下面的两个,咱们还须要下载个规定,规定的意思是依照下面规定查看 js 的谬误
// airbnb: eslint-config-airbnb-base eslint-plugin-import
// 除此之外还要在 package.json 中配置 eslintConfig
{
test: /\.js$/,
// 须要留神的是咱们只须要查看本人的源代码,第三方的库是不必查看的
exclude: /node_modules|css/,
// 只查看 src 文件夹上面的文件
// include: resolve(__dirname, 'src'),
// 优先执行,比方 eslint 和 babel 这里两个,eslint 就要先执行,不然就非常容易报错
enforce: 'pre',
// 延后执行,不写是两头执行
// enforce: 'post',
loader: 'eslint-loader',
options: {
// 开启 eslint 主动修复 eslint 的谬误
fix: true
}
},
{
// 以下 loader 只会匹配一个,防止每个文件都过了一遍 loader,次要是生产环境的打包速度优化
// 留神:不能有两个配置解决批准类型文件,比方 babel-loader 和 eslint-loader 都要解决 js,那样只会执行一个,所以把其中一个还间接放在 rules 中
oneOf: [
// css 文件解决
{
// 正则匹配文件
test: /\.css$/,
// 指定须要应用的 loader
// use 数组中 loader 执行程序是,从右到左,从下到上
// use 外面能够是间接的字符串,也能够是对象,应用对象通常使咱们要批改外面的配置
use: [
// 创立一个 style 标签,将 js 中的款式资源插入到进去,增加到 head 中失效
// 'style-loader',
// 和下面 style-loader 不同的是,应用插件,能够把 css 独自打包进去
{
loader: MiniCssExtractPlugin.loader,
options: {publicPath: '../'}
},
// 将 css 文件,变成 commonjs 模块,加载到 js 中。外面的内容是款式字符串
'css-loader',
// css 兼容性解决,须要用到 postcss,须要下载 postcss-loader 和 postcss-preset-env
{
loader: 'postcss-loader',
options: {
postcssOptions: {
ident: 'postcss',
plugins: () => {require('postcss-preset-env')()}
}
}
}
]
},
// less 文件解决
{
// 正则匹配文件
test: /\.less$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {publicPath: '../'}
},
'css-loader',
// css 兼容性解决,须要用到 postcss,须要下载 postcss-loader 和 postcss-preset-env
{
loader: 'postcss-loader',
options: {
postcssOptions: {
ident: 'postcss',
plugins: () => {require('postcss-preset-env')()}
}
}
},
'less-loader'
]
},
// 图片解决
{
// 正则匹配文件
test: /\.(jpg|png|gif|jpeg)$/,
// 因为 url-loader 依赖于 file-loader,所以要下载两个 loader
loader: 'url-loader',
options: {
// 图片小于 8kb, 会被转换成 base64,
// 长处:缩小申请数量,加重服务器压力
// 毛病:图片提及会更大,文件申请诉速度会更慢
limit: 8092,
// 手动设置图片的名字(能够不设置):name(图片原来的名字),hash(hash 值,10 代表去前 10 位),ext(图片原来的格局)name: '[name].[hash:10].[ext]',
// 因为文件的引入是 es6 语法,然而 webpack 是遵循 commonjs 规定的,所以想要 html 文件中想要应用图片,必须把 es6 关掉。这是给上面的 html 中图片解决用的
esModule: false,
// 指定打包后文件输入地位
outputPath: 'assets/imgs'
}
},
// html 中图片解决
{
// 正则匹配文件
test: /\.html$/,
loader: 'html-loader',
},
// 解决其余类型文件
{
// 排除 css,js,html 等文件,应用这个打包形式
exclude: /\.(html|js|css|less|png|jpg|jpeg|gif)/,
loader: 'file-loader',
options: {name: '[name].[hash:10].[ext]',
outputPath: 'assets'
}
},
// JS 的兼容解决,即 ES6 转 ES5:babel-loader, @babel/core, @babel/preset-env
// @babel/preset-env 只做根本语法的转换
// @babel/polyfill 做全类型转换,然而有一点,咱们只须要做局部的转换,全副引入,体积就会太大了
// 按需加载:应用 core.js
{
test: /\.js$/,
exclude: /node_modules|css/,
loader: 'babel-loader',
options: {
// 预设:批示 babel 做怎么样的兼容解决
presets: [
[
'@babel/preset-env',
{
// 按需加载
useBuiltIns: 'usage',
// 指定 core-js 版本
corejs: {version: 3},
// 指定兼容性做到浏览器的那个版本
targets: {
chrome: '60',
firefox: '50',
ie: '9',
safari: '10',
edge: '15'
}
}
]
],
// 开启 babel 缓存
// 第二次构建时,会读取之前的缓存
// 次要是防止多个 js 的状况下,只批改其中一个或一部分,导致所有的 js 都要再构建一次
cacheDirectory:true
}
}
]
},
]
},
// plugins 的配置
plugins: [
// 解决 html
// html-webpack-plugin
// 性能:默认会创立一个空的 HTML 文件,主动引入打包好的所有资源
new HtmlWebpackPlugin({
// 复制 './src/index.html' 文件到打包好的文件中,并引入所有资源
template: './src/index.html',
// 压缩 html 代码
// minify: {
// // 移除空格
// collapseWhitespace: true,
// // 移除正文
// removeComments: true
// }
}),
// css 独自提出来
new MiniCssExtractPlugin({
// 应用 contenthash,能够让 css 应用缓存,只有当 css 批改才会从新打包,而 hash 和 chunkhash 都不行,因为 hash 每次打包都不一样,而 chunkhash 不行是因为 css 是在 js 中引入的,所以每次也都是变动的
filename: 'css/built.[contenthash:10].css'
}),
// 压缩 css
// new OptimizeCssAssetsWebpackPlugin()
// 通知 webpack 哪些库不参加打包,同时应用时的名称也须要扭转
new webpack.DllReferencePlugin({manifest: resolve(__dirname, 'dll/manifest.json')
}),
// 将某个文件打包输入进来,并在 html 中主动引入改文件(给 dll 性能应用的)new AddAssetHtmlWebpackPlugin({filepath: resolve(__dirname, 'dll/jquery.js')
})
],
// 模式
mode: 'development', // 开发模式
// mode: 'production', // 生产模式,该模式会主动压缩代码
// 开发服务器 devServer: 用来自动化的编译,关上浏览器,主动刷新浏览器
// 自会在内存中编译打包,不会有任何的输入
devServer: {
// 我的项目构建后门路
contentBase: resolve(__dirname, 'dist'),
// 是否在首次编译后主动关上浏览器
open: true,
// 启动 gzip 压缩
compress: true,
// 地址
host: '127.0.0.1',
// 端口好
port: 8527,
/*
开启 HMR 性能,HMR:hot module replace(热加载)* css 在 hot: true 默认开启 HMR
* js 默认没有开启 HMR
- 入口 JS 文件不须要开启 HMR,所以须要监听的是其余模块
- 其余 JS 文件的监听形式是在入口 JS 外面写一个监听代码
if(module.hot) {
// 办法会监听 add.js 文件,一旦发生变化,其余模块会从新打包构建
// 而后执行前面的回调函数
module.hot.accept('./asstes/js/add.js',function() {add()
})
}
* html 默认没有开启 HMR,而且同时会导致 html 的热更新生效,复原热更新须要批改 entry --> entry: ['./src/index.js','./src/index.html'],然而还是没有 HMR,html 也不须要 HMR,尤其是单页面只有一个 index.html 的状况下
- 额定说:热更新和热加载不一样:- 热更新:文件内动改变后,整个页面刷新,不保留任何状态(比方输出过内容的 Input 表单),相当于 webpack 帮你摁了 F5 刷新
- 热加载:文件改变后,以最小的代价扭转被扭转的区域。尽可能保留改变文件前的状态(对 input 输出内容后,批改其余标签的代码)*/
hot: true,
// 监督 contentBase 目录下的所有文件,一旦文件变动就会 reload
watchContentBase: true,
// 监督文件的配置
watchOptions: {
// 疏忽要监督的文件
ignored: /node_modules/
},
// 不要显示启动服务器日志信息
clientLogLevel: 'none',
// 除了一些根本的启动信息外,其余内容都不要显示
quiet: true,
// 如果出错了,不要全屏提醒
overlay: false,
// 服务器代理:解决开发环境跨域问题
proxy: {// 一旦 devServer(8527)服务器接管到 /api/xxx 的申请,就会转发到另个服务器上(3000)'/api': {
target: 'http://localhost:3000',
// 发送申请时,申请门路重写,将 /api/xxx --> /xxx (去掉了 /api)
pathRewrite: {'^/api': ''}
}
}
},
// 提供源代码到构建后代码映射技术
devtool: 'eval-source-map',
/*
文件离开打包的第二种模式
能够将 node_modules 中代码独自打包成一个 chunk 最终输入,入口文件独自一个 chunk
下面的是单入口文件,该性能还会主动剖析多入口 chunk 中,有没有公共的文件,如果有会打包成一个独自的 chunk
*/
// optimization: {
// splitChunks: {
// chunks: 'all'
// }
// },
// 用来解决咱们不须要本人打包,而是通过 cdn 引入的一些文件
// externals: {
// // 回绝某个文件被打包
// jquery: 'jQuery'
// }
// 解析模块的规定
resolve: {
// 配置解析模块门路的别名,长处是简写门路,毛病是没有门路提醒
alias: {$css: resolve(__dirname, 'src/css')
},
// 配置省略文件门路的后缀名
// extensions: ['js','json','jsx'],
// 通知 webpack 解析模块是去找哪个目录
modules: [resolve(__dirname,'../node_modules'),'node_modules']
}
}
/*
tree shaking: 必须在 production 模式下,另外一个条件是,须要应用 ES6 的模块化,在这两个条件满足的状况下,会主动去除无用代码,较少代码体积
PS: 有的版本的 treeshaking 有点问题,会把 css 当成无用代码干掉,这个时候须要在 package.json 中增加点配置
- "sideEffects": ["*.css","*.less"] 意思是避开 css 和 less 文件进行 tree shaking
- "sideEffects": false 意思是所有文件都能够进行 tree shaking
*/
/*
source-map: 提供源代码到构建后代码映射技术(如果构建后代码出错了,通过映射能够追踪源代码的谬误)source-map: 内部
- 错误代码精确信息 和 源代码的谬误地位
inline-source-map: 内联
- 只生成一个内联 source-map
- 错误代码精确信息 和 源代码的谬误地位
hidden-source-map: 内部
- 错误代码的谬误起因,然而没有提醒谬误地位
- 不追踪源代码的谬误,只能提醒到构建后代码的谬误地位
eval-source-map: 内联
- 每一个文件都生成对应的 source-map,都在 eval
- 错误代码精确信息 和 源代码的谬误地位
nosource-source-map: 内部
- 错误代码精确信息,然而没有人任何源代码信息
cheap-source-map: 内部
- 错误代码精确信息 和 源代码的谬误地位
- 只能准确到行,然而不能准确到行的哪一块出错
cheap-module-source-map: 内部
- 错误代码精确信息 和 源代码的谬误地位
- module 会将 loader 的 source-map 退出
内联和内部的区别:1. 内部生成了文件,内联没有
2. 内联构建速度更快
开发环境:速度快,调试敌对
- 速度快(eval>inline>cheap>...)+ eval-cheap-source-map 这个组合最快
+ eval-source-map
- 调试更敌对
+ source-map
+ cheap-module-source-map
+ cheap-source-map
- 个别开发环境用 eval-source-map
生产环境:源代码要不要暗藏,调试要不要敌对
- 内联会让体积变大,所以生产环境不要用内联
- nosource-source-map: 全副代码暗藏
- hidden-source-map: 只暗藏源代码,会提醒构建后代码错误信息
- 个别生产环境用 source-map
*/