不推荐全局安装
npm install webpack webpack-cli -g
推荐项目中安装
npm install webpack webpack-cli -D
npx webpack -v
npx帮助在当前项目的node_modules中找webpack
配置文件 webpack.config.js
module.exports = {}
mode: 'production',(默认模式 压缩)
//devtool: 'cheap-module-eval-source-map'(映射关系),
devtool: 'cheap-module-source-map',
entry: {
main: './index.js',
sub: './index.js',
},
devServer: { //ajax请求必须在http://下的index下
//webpackDevMiddleware complier
contentBase: './dist', //项目在电脑内存
open: true,
proxy: {
'/api': 'http://localhost:3000' //跨域代理
},
hot: true, //HMR
hotOnly: true
},
modules: {
rules: [
{
test: '/\.(js)$/',
exclude: /node_modules/,
loader: 'babel-loader',//babel与webpack的桥梁
options: { //可以写到.babelrc文件里面
presents: [
['@babel/preset-env', { //翻译
targets: {
chrome: "67", //兼容到哪个版本的chrome 29kb
},
useBuiltIns: 'usage' //按需集成对象 161kb
}]
'@babel/preset-react' //由下而上
]
//plugins: [['@babelplugins-transform-runtime', { //写库的方案
//'corejs': 2,
//'helpers': true,
//'regenerator': true,
//'useESModules': false
//}]],
plugins: ["@babel/plugin-syntax-dynamic-import"], //支持import异步加载
}
},
{
test: '/\.(jpg|png|gif)$/',
use: {
loader: 'url-loader',
options: {
name: '[name].[ext] ',
outputPath: 'images/',
limit: 20480
}
}
},
{
test: '/\.(eot|ttf|svg)$/',
use: {
loader: 'file-loader',
}
},
{
test: '/\.less$/',
use: {
loader: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2, //import的css也会走下面两个
modules: true //css module / import style from './index.css' classList.add(style.title)
}
},
'less-loader',
'postcss-loader'
]
}
}
]
},
//plugin可以在webpack运行到某个时刻帮你做一些事情 就像生命周期
plugins: [
new HtmlWebpackPlugin({
template: 'src/index.html'
},
new CleanWebpackPlugin(['dist' ], {
root: path.resolve(__dirname, "../")
}), //打包结束后自动生成一个html文件并把js自动引入
new webpack.HotModuleReplacementPlugin(), //HMR 不要直接刷新
//babel-present vue-loader css -loader 都内置了hmr的module.hot.accept代码
new webpack.ProvidePlugin({ // shimming 垫片
$: 'jquery' //当发现模块里面用了$, 自动帮你引入jquery
})
],
optimization: {
usedExports: true, //tree shaking 生产环自动生效不用配置
splitChunks: { //code splitting 同步加载lodash代码分割 splitChunksPlugin 起到第二次加载的缓存性能优化
chunks: 'all',
cacheGroups: { //lodash分包取名生效
vendors: false,
default: false
}
}
},
output: {
publicPath: 'http://cdn.com.cn',
filename: '[name].[contenthash].js', // 浏览器缓存caching
chunkName: '[name].[contenthash].js',
path: path.resolve(__dirname, '../dist'),
}
import '@babel/polyfill'
// webpack配置后可去除这行代码
//为低版本浏览器集成promise map等所有对象一并打包 29kb->880kb
//如果只写个内库集成的对象会污染全局
//tree-shaking 引入什么打包什么 只支持es module这种静态引入的方式
package.json
{
'sideEffects':["@babel/polly-fill", "*.css"],
//import "@babel/polly-fill" tree-shaking可能就忽略掉了 因为没有导出任何内容
function getComponent() {
//注释分包取名
return import(/* webpackChunkName: "lodash"*/'lodash').then(({ default: _ })=>{ //异步加载lodash 自动代码分割打包
var element = document.createElement('div')
element.innerHTML = _.join(['Dell', 'Lee'], '-')
return element
})
//const {default: _} = await import (/* webpackChunkName: "lodash"*/'lodash')
}
getComponent().then(element => {
document.body.appendChild(element)
})
懒加载
document.addEventListener('click', ()=>{
getComponent().then(element => {
document.body.appendChild(element)
})
})
打包分析
chrome coverage 代码使用率
document.addEventListener('click', ()=>{
var element = document.createElement('div')
element.innerHTML = 'Dell Lee'
document.body.appendChild(element)
})
不会执行的代码你让页面去下载下来就会浪费页面执行的性能 应该把它放到异步加载的模块里来写
// click.js
function handleClick() {
var element = document.createElement('div')
element.innerHTML = 'Dell Lee'
document.body.appendChild(element)
}
export default handleClick
document.addEventListener('click', ()=>{
import('./click.js').then(({default: func})=>{
func()
})
})
多写异步代码才能让网站性能得到真正意义上的提升 同步分割只是增加一个缓存 意义不大
preloading prefetching
在网络空闲就去下载交互代码 而不是点击时才下载 最优方案
document.addEventListener('click', ()=>{
// 魔法注释
import(/* webpackPrefech: true*/'./click.js').then(({default: func})=>{
func()
})
})
网友评论