2019-07-15
Webpack
0

目录

npx webpack
常见loader
devtool理解
dev-server理解
Tree Shaking理解
splitChunks,runtimeChunk理解
splitChunks
runtimeChunk
preload prefetch
环境变量定义
webpack 性能优化
dll
PWA

Webpack是一个现代化的JavaScript应用程序的模块打包工具,它可以将各种静态资源(包括JavaScript、CSS、图片、字体等)打包成一个或多个JavaScript文件,以便于在浏览器中加载和运行。Webpack具有强大的模块化支持,可以通过各种插件和loader扩展其功能,使得它成为JavaScript应用程序开发中不可或缺的工具之一。

npx webpack

npx webpack index.js

webpack会用默认配置对index.js进行处理,例如: 创建文件夹dist,index.js内容输出到dist/main.js 必须添加入口文件,npx webpack 则会报错。

npx webpack

webpack,默认以根目录下的webpack.config.js为配置文件,配置项如果添加了入口文件,就不需要npx webpack index.js显示指定入口文件了。 当然你也可以指定其他文件为配置文件,只需要npx webpack --config webpackConfig.js。

常见loader

file-loader:(可作用于字体,图片,音频等多种文件)将文件打包至文件夹(会存在于文件)

url-loader:(可作用于字体,图片,音频等多种文件),与file-loader一致,是将文件打包成base64内联(不会存在文件)

sass-loader:解析scss,sass文件

postcss-loader:通过postcss插件,对css文件进行处理,比如autoprefixer,postcss-pxtorem

css-loader:解析css文件,参数 importLoaders => 用于配置「css-loader 作用于 @import 的资源之前」有多少个 loader。 参数 modules => 设置为true时,可以通过模块化引入css时,标签元素不会被模块化,但是所有被处理过后的都会变成独立的,无法全局引入css

style-loader:将css文件内容内联到style

devtool理解

image.png

  • inline-source-map:source-map内联进js代码(速度比较慢,报错会映射行和列)
  • cheap-source-map:(速度比较快,报错会映射行,但是不会映射列)
  • cheap-module-source-map:会保留源自 loader 的 source map(其余和cheap-source-map一致)
  • eval-source-map:(速度比较快,使用eval的方式输出)
  • source-map:完整的报错信息(精确映射行,列)

dev-server理解

npx webpack -w

根据webpack.config.js的配置,文件每次修改都会产生实际的修改后的文件,构建速度慢,而且需要手动刷新页面

webpack-dev-server

根据webpack.config.js的配置,文件每次修改都会在内存中产生文件,构建速度更快,不需要自己手动刷新页面

自己编写server

根据webpack.config.js的配置,文件每次修改都会在内存中产生文件,构建速度更快,需要手动刷新页面

js
const webpack = require('webpack'); const middleware = require('webpack-dev-middleware'); const config=require('./webpack.config') const compiler = webpack(config); const express = require('express'); const app = express(); app.use(middleware(compiler, {})); app.listen(3000, () => console.log('Example app listening on port 3000!'));

webpack-dev-server 手动监听热更新

js
if (module.hot) { module.hot.accept('./print.js', function() { console.log('Accepting the updated printMe module!'); printMe(); }) }

Tree Shaking理解

只支持ES Module的模块引入(因为ES Module 是静态引入)可以摇走无用的代码

webpack4 mode模式为produciton的时候默认引入

js
optimization: { usedExports: true }

package.json里面sideEffects字段:"sideEffects"

值为false的情况下所有文件的都会进行检测,最好别填,会有默认配置或者["@babel/polyfill","*.css"]可以忽略这些文件

splitChunks,runtimeChunk理解

splitChunks

1.进行如下配置,将自动把用到的插件统一打成一个js

js
optimization: { splitChunks:{ chunks:'all' } }
js
import _ from 'lodash' import axios from 'axios'

lodash和axios都会被打包成vendords-main.js

2.import异步导入时,会自动分割模块代码分割,例如:

js
function get() { return import(/* webpackChunkName: "lodash" */'lodash').then((s) => { console.log(s.default.join(['a', 'b', 'c'])) }) } get()

此时的lodash会被单独打成vendor~lodash.js,没有显示定义名字则为0.js。 如果异步用到的包,在插件里面有被使用到,则splitChunks会很智能的把相同模块的内容,打到vendords-main.js插件包里面去

3.如果定义了名字,所有的模块都会被打包成一个vendor.js(包括异步模块和插件)

js
optimization: { splitChunks: { chunks: 'all', name: 'vendor' } }

4.分包配置

js
config.optimization.splitChunks({ chunks: 'all', cacheGroups: { libs: { name: 'chunk-libs', test: /[\\/]node_modules[\\/]/, priority: 10, chunks: 'initial' // 只打包初始时依赖的第三方 }, vant: { name: 'chunk-vant', // 单独将 vant 拆包 priority: 20, // 权重要大于 libs 和 app 不然会被打包进 libs 或者 app test: /[\\/]node_modules[\\/]vant[\\/]/ }, commons: { name: 'chunk-commons', test: resolve('src/components'), // 可自定义拓展你的规则 minChunks: 3, // 最小公用次数 priority: 5, reuseExistingChunk: true } } })

runtimeChunk

它的作用是将包含chunks 映射关系的 list单独从 app.js里提取出来,因为每一个 chunk 的 id 基本都是基于内容 hash 出来的,所以你每次改动都会影响它,如果不将它提取出来的话,等于app.js每次都会改变。

js
config.optimization.runtimeChunk({ name:'manifest' })

preload prefetch

Preload 是一个声明式 fetch,可以强制浏览器在不阻塞 document 的 onload 事件的情况下请求资源。 Preload通常用于本页面要用到的关键资源,包括关键js、字体、css文件。Preload将会把资源得下载顺序权重提高,使得关键数据提前下载好,优化页面打开速度。

Prefetch 告诉浏览器这个资源将来可能需要,但是什么时间加载这个资源是由浏览器来决定的。 也就是说prefetch通常用于加速下一次导航,而不是本次的。

环境变量定义

可以在启动命令时设置环境变量,

json
"scripts": { "bundle": "webpack", "dev": "webpack-dev-server --env.development", "build":"webpack --env.production" }

但是这种环境变量只有在配置文件里面使用函数导出才能被读取,

js
module.exports=(env)=>{ if(env.production){ console.log('生产环境') } return { } }

process.env读取不到这样定义的变量,需要被读取到,使用cross-env

webpack 性能优化

  • node,npm,yarn版本尽可能的新
  • 用好loader的include,exclude,不对无用模块进行loader处理
  • plugin环境区分,比如开发环境不使用代码压缩,分割之类的
  • resolve extensions尽量少配置,资源查找时会有损耗
  • 第三方模块提前打包dll

dll

1.第三方模块打包,且生成包的映射关系

添加命令:

json
"dll": "webpack --config ./dll/webpack.dll.js",

执行命令,生成dll.js和dll.json,生成的dll需要带hash,避免缓存。DllPlugin的name需要和library相同。

dll/webpack.dll.js

js
const path=require('path') const webpack=require('webpack') module.exports={ mode:'production', entry:{ dll:['axios','better-scroll','vue','vue-router','vuex'] }, output:{ filename:'chunk-[name].[chunkhash:8].js', path:path.resolve(__dirname,'./'), library:'[name]' }, plugins:[ new webpack.DllPlugin({ name:'[name]', path:path.resolve(__dirname,'./chunk-[name].manifest.json') }) ] }

2.生产环境下,使用dll

js
const webpack=require('webpack') const path = require('path') const AddAssetHtmlPlugin=require('add-asset-html-webpack-plugin') new AddAssetHtmlPlugin({ filepath:path.resolve(__dirname, './dll/chunk-dll.*.js'), outputPath:'js', publicPath:`${publicPath}js` }), //dll.js添加 new webpack.DllReferencePlugin({ manifest:path.resolve(__dirname, './dll/chunk-dll.manifest.json') }) //dll 映射关系

PWA

navigator.serviceWorker只在HTTPS或者localhost生效

webpack配置

js
const workBoxPlugin=require('workbox-webpack-plugin') new workBoxPlugin.GenerateSW({ clientsClaim:true, skipWaiting:true })

main.js入口文件配置

js
if('serviceWorker' in navigator){ window.addEventListener('load',()=>{ navigator.serviceWorker.register('./service-worker.js').then((res)=>{ console.log('pwa success',res) }).catch((err)=>{console.log('pwa error',err)}) }) } workbox.setConfig({debug: false}); 关闭console log信息

本文作者:BARM

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!