webpack(二)

160 阅读3分钟
15.Source Map(12中)

生成bundle.js.map文件,调试源代码

devtool: 'source-map',

// eval模式下的source-map 只知道文件名称
// eval('console.log(123)')
devtool: 'eval',
    
devtool: 'eval',
const HtmlWebpackPlugin = require('html-webpack-plugin')

const allModes = [
	'eval',
	'cheap-eval-source-map',
	'cheap-module-eval-source-map',
	'eval-source-map',
	'cheap-source-map',
	'cheap-module-source-map',
	'inline-cheap-source-map',
	'inline-cheap-module-source-map',
	'source-map',
	'inline-source-map',
	'hidden-source-map',
	'nosources-source-map'
]

module.exports = allModes.map(item => {
	return {
		devtool: item,
		mode: 'none',
		entry: './src/main.js',
		output: {
			filename: `js/${item}.js`
		},
		module: {
			rules: [
				{
					test: /.js$/,
					use: {
						loader: 'babel-loader',
						options: {
							presets: ['@babel/preset-env']
						}
					}
				}
			]
		},
		plugins: [
			new HtmlWebpackPlugin({
				filename: `${item}.html`
			})
		]
	}
})
16.选择合适的source-map
// 开发环境  'cheap-eval-source-map',
// 生产环境  'nosources-source-map'
17.Webpack 自动刷新问题
// 编辑器文本自动刷新
18.Webpack HMR体验(Hot Module Replacement)模块热替换(热拔插)

webpack最强大的功能之一

热替换只将修改的模块实时替换到应用中,不必完全刷新应用

// 开启HMR
const webpack = require('webpack')

devServer: {
  hot: true,  // css可以热替换js不行(脚手架可以内部集成了HMR方案) 
}
plugins: [
  new webpack.HotModuleReplacementPlugin()
]
19.Webpack使用HMR API
// 入口文件main.js  editor模块

const editor = createEditor()
document.body.appendChild(editor)

const img = new Image()
img.src = background
document.body.appendChild(img)

// ============ 以下用于处理 HMR,与业务代码无关 ============

// console.log(createEditor)
let lastEditor = editor
module.hot.accept('./editor', () => {
  // console.log('editor 模块更新了,需要这里手动处理热替换逻辑')
  // console.log(createEditor)
  const value = lastEditor.innerHTML
  document.body.removeChild(lastEditor)
  const newEditor = createEditor()
  newEditor.innerHTML = value
  document.body.appendChild(newEditor)
  lastEditor = newEditor
})
20.Webpack处理图片模块热替换
import background from './better.png'
const img = new Image()
img.src = background
document.body.appendChild(img)

 module.hot.accept('./better.png', () => {
   img.src = background  // 修改图片后图片文件名会发生变化
   console.log(background)
 })
21.Webpack HMR注意事项
  • 处理HMR的代码报错会导致自动刷新
devServer: {
  hotOnly: true 
  // 只使用 HMR,不会 fallback  live reloading,处理HMR的代码报错就不会导致自动刷新
},
  • 不使用new webpack.HotModuleReplacementPlugin()会报错
if (module.hot) {  // 添加判断
  let lastEditor = editor
  module.hot.accept('./editor', () => {
    const value = lastEditor.innerHTML
    document.body.removeChild(lastEditor)
    const newEditor = createEditor()
    newEditor.innerHTML = value
    document.body.appendChild(newEditor)
    lastEditor = newEditor
  })

  module.hot.accept('./better.png', () => {
    img.src = background
    console.log(background)
  })
}
  • 代码中有很多与业务无关的代码

分包

chunkIds: 'natural'

当前文件的名称是按自然数进行编号排序,如果某个文件不再被依赖,那么重新打包序号都会变

不利于浏览器缓存

optimization: {
    chunkIds: 'deterministic'
}
​
output: {
    chunkFileName: 'js/chunk_[name].js'
}
​
// 魔法注释
/* webpackChunkName */

runtimeChunk优化配置

依赖单独抽离,记录import加载和解析的规则

runtimeChunk: true // 有利于浏览器长期缓存
​
output: {
    fileName: 'js/[name].[contenthash: 8].bundle.js'
}
runtimeChunk: "single" // 把公共的依赖抽取到一个文件

代码懒加载

// 可能产生等待

import('./index.js')

预获取/预加载prefetch和preload

prefetch浏览器空闲时加载

preload立即加载

// 代码懒加载可能产生等待

import(
    /*webpackChunkName: 'title'*/
    /*webpackPrefetch: true*/
    './title.js')
​
import(
    /*webpackChunkName: 'title'*/
    /* webpackPreload: true */
    './title.js')

第三方扩展设置CDN

output: {
    publicPath: 'http://aaa/cdn'  // 自己的服务器
}
// 外部依赖不需打包
externals: {
    lodash: '_'
}
​
// index.html
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script>

inlineChunkHtmlPlugin

向页面注入内容

const inlineChunkHtmlPlugin = require('inline-chunk-html-plugin')
const htmlWebpackPlugin = require('html-webpack-plugin')
​
new inlineChunkHtmlPlugin(htmlWebpackPlugin, [/runtime.*.js/])

webpack打包Library

打包库文件

output: {
    libraryTarget: 'umd',
    library: 'syUtil', // 使用,暴露方法名
    globalObject: 'this'
}

打包时间和内容分析

speed-measure-webpack-plugin

// Change your webpack config from
const webpackConfig = {
  plugins: [new MyPlugin(), new MyOtherPlugin()],
};
​
// to
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");
​
const smp = new SpeedMeasurePlugin();
​
const webpackConfig = smp.wrap({
  plugins: [new MyPlugin(), new MyOtherPlugin()],
});

webpack-bundle-analyzer

const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;module.exports = {
  plugins: [
    new BundleAnalyzerPlugin()
  ]
}

\