本文共 13396 字,大约阅读时间需要 44 分钟。
上面的到爆工具解决的是前端整体的模块化并不单指Javascript模块化
const path = require('path');module.exports={ entry:'./src/main.js', //文件入口 output:{ //输出目录 filname:'bundle.js', //输出文件名称 path:path.join(_dirname,'output') //在outuput文件里面生成bundle.js文件 //指定输出文件的目录(需要绝对路径) }}
借助loader可以加载任何形式的资源(loader对于同一个源可以依次使用多个loader,通过多个loader完成同一个功能。例如style-loader,css-loader)
dataUrl 可以用base64编码进行表示任何文件 url-loader
import icon from './icon.png'const img = new Image();img.src = icon;document.body.append(img);
import footerHtml from './footer.html'documnet.write(footerHtml)
// 使用module:module:{ rules:[ { test:'/.js$/', use: { loader:'babel-loader', options:{ presets:['@babel/preset-env'] } }, }, { //将css转换成js的模块 test:'/.css$/', //这里需要注意 数组中的执行顺序是从右往左执行的 必须先解析css在加载style-loader use:['style-loader',css-loader'] }, { test:'/.png$', // use:'file-loader'url // use:'url-loader' use:{ loader:'url-loader', options:{ limit:10*1024 //10kb } } }, { test:'/.html$/', loader:'html-loader' //html中img src属性触发打包如果想让别的也触发可以进行如下配置 options:{ attrs:['img:src','a:href'] } } ]}
* 编译转化加载类(css-loader)* 文件操作类型加载器(file-loader)* 代码检查加载器
需要注意我们平时写的项目要求前后端分离 webpack建议我们根据代码的需要动态导入资源,真正需要资源的不是应用,而是代码,代码什么时候需要就要加载,代码更新不需要资源这个时候就不需要加载,webpack驱动了整个前端的应用。
require('./header.js').default;
项目当中都会散落着各种各样的代码和资源文件,weboack会根据配置找到一个主入口文件一般都是.js的文件根据代码import export等依赖的模块和整个的模块依赖,形成依赖数,webpack会递归遍历依赖数,找到每个节点的所对应的资源文件,根据模块对应的ruls找到模块对应的加载器,然后交给对应的加载器加载模块,加载到的结果放到bundle.js文件中,实现项目的打包。loader是webpack的核心。
自己开发一个markdown-loader,注意你可以使用多个loader但是最终返回的结果是一个javascript的代码
markdown-loader.jsconst marked = required('marked');module.exports = source =>{ const html = marked(source); // 第一种导出将 导出内容直接转化成javascript的格式 //以下两种格式都支持导出 //第二种格式 返回的html字符串直接交给下一个loader来处理 return html; }配置webpack.json//返回javascript的格式{ test:'./md$/', use:'./markdown-loader' //不仅可以使用模块还可以使用路径地址}//返回html的格式{ test:'./md$/', use:['html-loader','./markdown-loader'] //再次强调数组的执行顺序是从后面像前面执行的}
loader处理资源 plugin处理那些非资源的内容实现了大多的功能
<%= htmlwebpackPlugin.options.title %>
const { CleanWebpackPlugin} = require('clean-webpack-plugin') const HtmlWebpackPlugin = require('html-webpack-plugin') //默认导出的插件类型const CopyWebpackPlugin = require('copy-webpack-plugin') plugins:[ new CleanWebpackPlugin() new HtmlWebpackPlugin({ //生成index.html title:'webpack', meta:{ viewport:'width=device-width' }, template:'./src/index.html' }) //添加多个实例输出多个文件 new HtmlWebpackPlugin({ filename:'about.html' }), //接受的是一个数组,可以写路径,目录,通配符等 new CopyWebpackPlugin([ 'public' //public/** ])]
定义插件一个函数或者是一个包含apply方法对象
// 清除bundle.js中没用注释 emit在webpack输出文件时候执行class MyPlugin { apply(compiler) { console.log('Myplugin'); compiler.hooks.emit.tap('MyPlugin', compilation => { // compilation => 可以理解为此次打包的上下文 for (const name in compilation.assets) { //文件的名称 // console.log(compilation.assets[name].source()) //内容 if (name.endsWith('.js')) { const contents = compilation.assets[name].source(); console.log(contents); const withoutComments = contents.replace(/\/\*\*+\*\//g, ''); // /******/ \/\*\*+\*\/ compilation.assets[name] = { .//webpack必须要暴露出来的两个方法 source: () => withoutComments, size: () => withoutComments.length } } } }) }}在plugin中new MyPlugin();
yarn add webpack-dev-server --dev // 通过yarn运行cliyarn webpack-dev-server 运行命令会直接打包应用
*处理静态资源 webpack-dev-server
// 注释:上面代码中new CopyWebpackPlugin 可以实现资源的copy,但是一般new CopyWebpackPlugin都留在上线前的打包使用而已,因为在开发过程中每次打包都copy会影响速度。module.exports = { devServer:{ contentBase:['./public'] //指定静态资源 }}
devServer:{ contentBase:'./public', proxy:{ // 请求前缀 '/api':{ // http://localhost:8080/api/users -> https:api.geithub.com/api/users target:"https:api.github.com", //代理目标 pathRewrite:{ '^/api':'' //代理路径重写 }, //不能使用localhost:8080 作为请求GitHub的主机名 changeOrign:true } }}
devtool 开发过程中的辅助工具
原因:个人编写代码风格每一行不会超过80个字符,所以定义到行就可以了使用框架比较多,loader转化之后和之前都有很多差别,所以要选择有module首次打包启动会慢,但是重写打包速度较快
原因:会暴露源代码调试是开发阶段的事情,开发阶段尽量把所有的问题都找出来解决
## webpack dev server
webpack dev server刷新会对样式有影响,每次构建都需要刷新页面
第一种## webpack-dev-server --host第二种##devServer:{ hot:true // 如果出错可以报错不会自动刷新 hot:only}const webpack = require('webpack');plugins:[new webpack.HotModuleReplacementPlugin();]//启动 yarn webpack-dev-server --open
module.hot.accept('./editor',()=>{ })
module.exports = (env,argv){ //env cli传过来的参数 //argv 除了env之后的所有参数 if(env ==='production'){ config.mode = 'production' config.devtool = false config.plugins = [ ...config.plugins, new CleanWebpackPlugin(), new CopywebpackPlugin(['public']) ] } return config}//运行 yarn webpack --env production
// 一般有三个文件 一个线上一个开发 一个公共文件// ## webpack.prod.jsconst common = require(./webpack.common)const merge = require('webpack-merge')const { CleanWebpackPlugin} = require('clean-webpack-plugin')const CopyWebpackPlugin = require('copy-webpack-plugin')module.exports = merge(common,{ mode:'production', plugins:[ new CleanWebpackPlugin(), new CopyWebpackPlugin(['public']) ]})//单独运行 yarn webpack --config webpack.prod.js// ## webpack.dv.js// ## webpack.common.js// 公共配置const HtmlWebpackPlugin = require('html-webpack-plugin')module.exports = { entry:'./src/main.js', output:{ filename:'js/bundle.js' }, module:{ rules:[ { test:'/.js$/', use: { loader:'babel-loader', options:{ presets:['@babel/preset-env'] } }, }, { //将css转换成js的模块 test:'/.css$/', //这里需要注意 数组中的执行顺序是从右往左执行的 必须先解析css在加载style-loader use:['style-loader',css-loader'] }, { test:'/.png$', // use:'file-loader'url // use:'url-loader' use:{ loader:'url-loader', options:{ limit:10*1024 //10kb } } }, { test:'/.html$/', loader:'html-loader' //html中img src属性触发打包如果想让别的也触发可以进行如下配置 options:{ attrs:['img:src','a:href'] } } ] }}
const webpack = require('webpack');PLUGINS :[new webpack.DefinePlugin({ API_BASE_URL:'"https://api.example.com"'//JSON.stringigy 如果生产和开发的值不一样可以通过这个来注入})]
在生产模式下自动开启
module.exports = [ mode :'none', entry:'./src/index.js', output:{ filename:'bundle.js' }, optimization:{ //优化 usedExports:true, //只标记使用的代码, minimize:true, //把这些无用的摇掉 }]
optimization:{ //优化 concatenatModules:true //注释:平时打包会有很多模块函数,这样合并成一个,尽可能将所有的模块合并一个模块被称为 Scope Hoisting 作用域的提升,既提升了运行效率,又减少了代码体积}
Tree-shaking前提是ES Modles,由webpack打包的代码必须使用ESM,babel-loader处理代码时有可能会把esmodule转化成了comminjs 所以 tree-shaking就不会生效 在最新版本中babel支持了tree-shaking原因是 源代码中并没有转化esmodule
//自己配置 如果使用commonjs这个时候就不会执行tree-shaking{ test:/\.js$/, use:{ loader:'babel-loader', options:{ presets:[['@babel/preset-env',{ modules:'commonjs'}] //{modules:'commonjs'} 就不会执行 将modules:false就会禁止转化esmodule 所以会执行tree-shking } }}
模块执行除了导出成员之外所做的其他的事情 一般用于npm包标记是否有副作用
optimization:{ sideEffects:true, //打包看是否有标识看是否有副作用 如果没有则别移除}//在package.json中增加"sideEffects":false //标识当前项目没有副作用
解决方法:在package.json中"sideEffects":['./extend.js','./extnd.css'] 数组进行配置
并不是每个模块在启动的时候都需要加载 要不然bundle的文件过大
应用于多应用程序 一个页面提供一个打包入口 公共的可以提出
## 在entry 中进行配置多页面 记住是对象entry:{ index:'./src/index.js', album:'./src/album.js'}## 出口自动设置相应的文件output:[name].bundle.js## html中 new html-webpack-plgins中设置chunks:['index']另一个设置 chunks:['album']
多入口打包会存在公共的模块
例如index.js中和album.js中公共的模块使用了global.css的模块
optimization:{ splitChunks:{ chunks:'all' }}
const MiniCssExtractPlugin = require('mini-css-extract-plugin')//style-loader //将样式是通过style标签注入MiniCssExtractPlugin.loader,//如果文件小于150kb可以不用单独提出来css-loader //css 解析
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin');plugins:[ new OptimizeCssAssetsWebpackPlugin(); //配资到plugins中 都可以使用]optimization:{ minimizer:[ new OptimizeCssAssetsWebpackPlugin(); //配置到这里 在没有开启压缩的时候插件就不会工作 //需要注意的是配置了minimizer 这个时候打包默认手动填写,需要配置js打包压缩不然js无法压缩 new TerserWebpackPlugin() //需要安装和引用 ]}const TerserWebpackPlugin = ('terser-webpack-plugin')
在生产模式下,文件名使用hash
output:{ //针对项目,有一个发生改变就会重新生成 filename:'[name]-[hash].bundle.js' // 打包过程中同一类,改动哪里那个类js.css都会改变 filename:'[name]-[chunkhash].bundle.js' //解决缓存最好的方法 每个文件都有hashcontenthash:8 也可以指定位数 默认20 filename:'[name]-[contenthash].bundle.js'}
output 输出的必须是绝对路径
webpack加载资源的方式:
webpack本身只能打包js文件,但对于其他资源例如css,图片,或者其他的语法集比如jsx,是没有办法加载的,这就需要对应的loader将资源转化,加载进来
TreeShaking在生产模式会自动开启,他是一组功能搭配使用后的效果,起哄usedExports负责标记(枯树叶),sideEffects一般标记npm包标记是否有副作用
转载地址:http://chwiz.baihongyu.com/