简介webpack可以做的事代码转换文件优化代码分割模块合并自动刷新代码校验自动发布面试常见考点webpack常见配置webpack高级配置ast抽象语法树webpack中的Tapable掌握webpack流程,手写webpack手写webpack中常见的loader手写webpack中常见的pluginwebpack基础配置起步创建src—>index.jsnpx webpack基础配置//webpack是node写出来的,所以需要node的写法let path = require(‘path’) //核心模块module.exports = { mode: ‘development’, //默认两种:production development entry: ‘./src/index.js’, //入口 output: { //出口 filename: ‘bundle.js’, //打包后的文件名 path: path.resolve(__dirname, ‘dist’), //resolve把相对路径解析成绝对路径,__dirname意思是在当前目录建立一个,路径必须是一个绝对路径 }}script脚本手动配置:npx webpack –config webpack.config.js脚本配置:“scripts”: { “build”: “webpack” }//npm run build 传参npx webpack – –config webpack.config.jsHtml插件npx webpack-dev-server开发服务,内部通过express实现这种服务并不真实打包文件,只是在内存中生成htmlWebpackPlugin将打包后的js文件插入html文件,并放到build目录下let htmlWebpackPlugin = require(‘html-webpack-plugin’)module.exports = { devServer: { //开发服务器的配置 port: 3000, //设置端口号 progress: true, //进度条 contentBase: ‘/.build’, //指定静态目录 compress: true }, output: { filename: ‘bundle.[hash:8].js’, //文件名 path: path.resolve(__dirname, ‘dist’), }, plugins: [ //数组 放着所有的webpack插件 new htmlWebpackPlugin({ template: ‘./src/index.html’, //模板 filename: ‘index.html’, //打包后的文件名 minify: { //打包后的html也压缩 removeAttributeQuotes: true, //删除属性的双引号 collapseWhitespace: true, //折叠空行 }, hash: true //html文件加上哈希戳 }) ]}css配置loader:Webpack本身只能处理 JavaScript 模块,如果要处理其他类型的文件,就需要使用 loader 进行转换。Loader 可以理解为是模块和资源的转换器,它本身是一个函数,接受源文件作为参数,返回转换的结果css配置css-loader 解析@import这种语法style-loader把css插入到head的标签中loader的特点:希望单一loader的用法:字符串只用一个loader,多个loader需要[]loader的顺序:默认是从右向左执行       从下往上优先级{ loader: ‘style-loader’, options: { insertAt: ’top’ //确保优先级 }}处理less、sass、stylusyarn add less less-loaderyarn add node-sass sass-loaderyarn add stylus stylus-loadermodule.exports = { module: { //模块 rules: [ //规则 //loader的特点:希望单一 //{ test: /.css$/, use: [‘style-loader’, ‘css-loader’] } //第一种:写法 //loader还可以写成对象方式 { //处理less文件 test: /.css$/, use: [{ loader: ‘style-loader’, options: { insertAt: ’top’ //确保优先级 } }, ‘css-loader’, //@import 解析路径 ’less-loader’ //把less —->css ] } ] }}抽离CSS的插件默认打包后只能插入<style>标签内,我们希望抽离成<link>形式通过 mini-css-extract-plugin这个插件yarn add mini-css-extract-plugin -D插件都是类,插件的使用顺序没有先后let MiniCssExtractPlugin = require(‘mini-css-extract-plugin’)//配置pluginplugins: [ new MiniCssExtractPlugin({ filename: ‘main.css’, }) ],//配置module module: { rules: [{ test: /.css$/, use: [MiniCssExtractPlugin.loader, ‘css-loader’] }, { test: /.less$/, use: [MiniCssExtractPlugin.loader, ‘css-loader’, ’less-loader’] } ] } 自动添加前缀autoprefixer前提要用postcss-loaderyarn add postcss-loader autoprefixer//配置module//先处理post-css再处理cssmodule: { rules: [{ test: /.css$/, use: [MiniCssExtractPlugin.loader, ‘css-loader’,‘postcss-loader’] //加上post-css }, { test: /.less$/, use: [MiniCssExtractPlugin.loader, ‘css-loader’, ‘postcss-loader’, ’less-loader’] } ] }//创建postcss.config.js文件并配置module.exports = { plugins: [require(‘autoprefixer’)]}压缩css(同时保证js的压缩)通过optimize-css-assets-webpack-pluginyarn add optmize - css - assets - webpack - plugin - Duglifyjs-webpack-pluginlet path = require(‘path’)let htmlWebpackPlugin = require(‘html-webpack-plugin’)let MiniCssExtractPlugin = require(‘mini-css-extract-plugin’)let OptimizeCss = require(‘optimize-css-assets-webpack-plugin’)let UglifyJsPlugin = require(‘uglifyjs-webpakc-plugin’)module.exports = { Optimization: { //***优化项,用了这个插件之后就必须用一下Uglifyjs压缩js minimizer: [ new UglifyJsPlugin({ cache: true, //是否用缓存 parallel: true, //是否并行打包 sourceMap: true }), new OptimizeCss() ] }, devServer: { port: 3000, progress: true, contentBase: ‘/.build’ }, mode: ‘development’, entry: ‘./src/index.js’, output: { filename: ‘bundle.[hash:8].js’, path: path.resolve(__dirname, ‘dist’), }, plugins: [ new htmlWebpackPlugin({ template: ‘./src/index.html’, filename: ‘index.html’, minify: { removeAttributeQuotes: true, collapseWhitespace: true, }, hash: true }), new MiniCssExtractPlugin({ filename: ‘main.css’ }) ], module: { rules: [ //{ test: /.css$/, use: [‘style-loader’, ‘css-loader’] } { test: /.css$/, use: [ MiniCssExtractPlugin.loader, //**创建link标签,引用 ‘css-loader’, ’less-loader’, ‘postcss-loader’ ] } ] }}JS配置转化es6语法babelyarn add babel-loader @babel/core @babel/preset-env -D配置modulemodule: { rules: [{ test: /.js$/, use: { loader: ‘babel-loader’, options: { //用babel-loader es6—->es5 presets: [ ‘@babel/preset-env’ ] } } } ] } 配置提案里支持的语法class A{ a = 1;}yarn add @babel/plugin-proposal-class-properties -D{ test: /.js$/, use: { loader: ‘babel-loader’, options: { presets: [ ‘@babel/preset-env’ ], plugins: [ ‘@babel/plugin-proposal-class-properties’ ] } }}支持装饰器语法function log(target) { console.log(target, ‘23’)}log(A)yarn add @babel/plugin-proposal-decorators -D配置modulemodule: { rules: [{ test: /.js$/, use: { loader: ‘babel-loader’, options: { //用babel-loader es6—->es5 presets: [ ‘@babel/preset-env’ ], plugins: [ [’@babel/plugin-proposal-class-properties’], [’@babel/plugin-proposal-decorators’,{“legacy”:true}], [’@babel/plugin-transform-runtime’] ] } } } ] }处理JS语法及校验 function gen(params){ yield 1; } console.log(gen().next()); //内置API // Uncaught ReferenceError: regeneratorRuntime is not definedbabel-runtimeyarn add @babel/plugin-transform-runtime -Dyarn add @babel/runtimemodule: { rules: [{ test: /.js$/, use: { loader: ‘babel-loader’, options: { //用babel-loader es6—->es5 presets: [ ‘@babel/preset-env’ ], plugins: [ [’@babel/plugin-proposal-class-properties’], [’@babel/plugin-proposal-decorators’,{“legacy”:true}], [’@babel/plugin-transform-runtime’] ] } }, include:path.resolve(__dirname,‘src’), //包括查找范围 exclude:/node_module/ //排除查找范围 } ] }@babel/polyfill’aaa’.include(‘a’) //ES7语法//实例上的方法默认都不会解析 yarn add @babel/polyfill//a.jsrequire(’@babel/polyfill’)‘aaa’.include(‘a’)eslintyarn add eslint eslint-loadermodule: { rules: [ //loader默认从右向左执行 从下到上,写的太多容易乱,写到一起删除不方便 { test:.js$/, use:{ loader:’eslint-loader’, options:{ enforce:‘pre’ //previous -> normal-> post 顺序执行 } } } // ]} 选择好配置,下载.eslintrc.json到configuration全局变量引入问题第三方模块引用yarn add jqueryimport $ form ‘jqurey’console.log($) console.log(window.$) //undefined,并不会挂载到window上如何将变量暴露给window?expose-loader (内联loader)yarn add expose-loaderimport $ from ’expose-loader?$!jquery’ //将jquery作为$暴露给全局也可以在webpack.config.js中配module: { rules: [{ test: require.resolve(‘jquery’), use: ’expose-loader?$!jquery’ } ] } 在每个模块中注入$对象//webpack.config.jslet Webpack = require(‘webpack’) new Webpack.ProvidePlugin({ //再每个模块中都注入$符 jqurey: ‘$’})//index.jsconsole.log($) //只是在每个模块中都注入一个$//此时window.$ //undefinedcdn外部路径引入<script src=“https://cdn.bootcss.com/jquery/3.3.1/core.js"></script>//如果此时js也引入jquery会导致重复import $ form jqueryexternals: { jquery: ‘jQuery’ //告诉webpack从外部引入,并不需要打包,忽略 },总结expose-loader:暴露到window上providePlugin:给每个提供一个引入不打包loader类型pre             前面执行的loadernormal        普通的loaderliader        内联loaderpost            后置loader图片处理图片引入方式在js中创建图片来引入let image = new Image()image.src = ‘./logo.png’document.body.appendChild(image) //打包完,其实就是一个普通的字符串,并没有真正的引入图片file-loaderyarn add file-loader默认在内部生成图片,到build目录下,并且把生成的路径的名字返回回来//webpack.config.jsmodule: { rules: [{ test: /.(png|jpg|gif)$/, use: ‘file-loader’ } ]}//index.jsimport logo from ‘./logo.png’ //把图片引入,生成一个哈希戳的logo,返回的结果是一个新的图片console.log(logo)let image = new Image();image.src = logo;document.body.appendChild(image)在css中引入background(‘url’)<img src=”" alt="">打包文件分类打包多页应用配置source-map