本文共 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/