当前位置: 首页 > news >正文

怎么改网站模块做网站卖什么

怎么改网站模块,做网站卖什么,学生作业 制作一个网站,恒一信息深圳网站建设公司1前言2020年即将到来,在众多前端的招聘要求里,webpack、工程化这些字眼频率越来越高。日常开发者中#xff0c;我们常常在用诸如vue-cli、create-react-app的脚手架来构建我们的项目。但是如果你想在团队脱颖而出(鹤立鸡群)、拿到更好的offer(还房贷)#xff0c;那么你必须去深…前言2020年即将到来,在众多前端的招聘要求里,webpack、工程化这些字眼频率越来越高。日常开发者中我们常常在用诸如vue-cli、create-react-app的脚手架来构建我们的项目。但是如果你想在团队脱颖而出(鹤立鸡群)、拿到更好的offer(还房贷)那么你必须去深刻的认识下我们经常打交道的webpack 本文共分为三个部分带你领略webpack的魅力。如有不足之处恳请斧正1. 入门(一起来用这些小例子让你熟悉webpack的配置)1.1 初始化项目新建一个目录初始化npmnpm initwebpack是运行在node环境中的,我们需要安装以下两个npm包npm i -D webpack webpack-clinpm i -D 为npm install --save-dev的缩写npm i -S 为npm install --save的缩写新建一个文件夹src ,然后新建一个文件main.js,写一点代码测试一下console.log(call me 老yuan)配置package.json命令执行npm run build此时如果生成了一个dist文件夹并且内部含有main.js说明已经打包成功了1.2 开始我们自己的配置上面一个简单的例子只是webpack自己默认的配置下面我们要实现更加丰富的自定义配置新建一个build文件夹,里面新建一个webpack.config.js// webpack.config.jsconst path require(path); module.exports {mode:development, // 开发模式entry: path.resolve(__dirname,../src/main.js), // 入口文件output: {filename: output.js, // 打包后的文件名称path: path.resolve(__dirname,../dist) // 打包后的目录} }更改我们的打包命令执行 npm run build会发现生成了以下目录图片其中dist文件夹中的main.js就是我们需要在浏览器中实际运行的文件当然实际运用中不会仅仅如此,下面让我们通过实际案例带你快速入手webpack1.3 配置html模板js文件打包好了,但是我们不可能每次在html文件中手动引入打包好的js这里可能有的朋友会认为我们打包js文件名称不是一直是固定的嘛(output.js)这样每次就不用改动引入文件名称了呀实际上我们日常开发中往往会这样配置:module.exports {// 省略其他配置output: {filename: [name].[hash:8].js, // 打包后的文件名称path: path.resolve(__dirname,../dist) // 打包后的目录} }这时候生成的dist目录文件如下为了缓存你会发现打包好的js文件的名称每次都不一样。webpack打包出来的js文件我们需要引入到html中但是每次我们都手动修改js文件名显得很麻烦因此我们需要一个插件来帮我们完成这件事情npm i -D html-webpack-plugin新建一个build同级的文件夹public,里面新建一个index.html具体配置文件如下// webpack.config.js const path require(path); const HtmlWebpackPlugin require(html-webpack-plugin) module.exports {mode:development, // 开发模式entry: path.resolve(__dirname,../src/main.js), // 入口文件output: {filename: [name].[hash:8].js, // 打包后的文件名称path: path.resolve(__dirname,../dist) // 打包后的目录},plugins:[new HtmlWebpackPlugin({template:path.resolve(__dirname,../public/index.html)})] }生成目录如下(图片) 可以发现打包生成的js文件已经被自动引入html文件中1.3.1. 多入口文件如何开发生成多个html-webpack-plugin实例来解决这个问题const path require(path); const HtmlWebpackPlugin require(html-webpack-plugin) module.exports {mode:development, // 开发模式entry: {main:path.resolve(__dirname,../src/main.js),header:path.resolve(__dirname,../src/header.js)}, output: {filename: [name].[hash:8].js, // 打包后的文件名称path: path.resolve(__dirname,../dist) // 打包后的目录},plugins:[new HtmlWebpackPlugin({template:path.resolve(__dirname,../public/index.html),filename:index.html,chunks:[main] // 与入口文件对应的模块名}),new HtmlWebpackPlugin({template:path.resolve(__dirname,../public/header.html),filename:header.html,chunks:[header] // 与入口文件对应的模块名}),] }此时会发现生成以下目录1.3.2 clean-webpack-plugin每次执行npm run build 会发现dist文件夹里会残留上次打包的文件这里我们推荐一个plugin来帮我们在打包输出前清空文件夹clean-webpack-pluginconst {CleanWebpackPlugin} require(clean-webpack-plugin) module.exports {// ...省略其他配置plugins:[new CleanWebpackPlugin()] }1.4 引用CSS我们的入口文件是js所以我们在入口js中引入我们的css文件同时我们也需要一些loader来解析我们的css文件npm i -D style-loader css-loader如果我们使用less来构建样式则需要多安装两个npm i -D less less-loader配置文件如下// webpack.config.js module.exports {// ...省略其他配置module:{rules:[{test:/.css$/,use:[style-loader,css-loader] // 从右向左解析原则},{test:/.less$/,use:[style-loader,css-loader,less-loader] // 从右向左解析原则}]} }浏览器打开html如下1.4.1 为css添加浏览器前缀npm i -D postcss-loader autoprefixer配置如下// webpack.config.js module.exports {module:{rules:[test/.less$/,use:[style-loader,css-loader,postcss-loader,less-loader] // 从右向左解析原则]} }接下来我们还需要引入autoprefixer使其生效,这里有两种方式1在项目根目录下创建一个postcss.config.js文件配置如下module.exports {plugins: [require(autoprefixer)] // 引用该插件即可了 }2直接在webpack.config.js里配置// webpack.config.js module.exports {//...省略其他配置module:{rules:[{test:/.less$/,use:[style-loader,css-loader,{loader:postcss-loader,options:{plugins:[require(autoprefixer)]}},less-loader] // 从右向左解析原则}]} }这时候我们发现css通过style标签的方式添加到了html文件中但是如果样式文件很多全部添加到html中难免显得混乱。这时候我们想用把css拆分出来用外链的形式引入css文件怎么做呢这时候我们就需要借助插件来帮助我们1.4.2 拆分cssnpm i -D mini-css-extract-pluginwebpack 4.0以前我们通过extract-text-webpack-plugin插件把css样式从js文件中提取到单独的css文件中。webpack4.0以后官方推荐使用mini-css-extract-plugin插件来打包css文件配置文件如下const MiniCssExtractPlugin require(mini-css-extract-plugin); module.exports {//...省略其他配置module: {rules: [{test: /.less$/,use: [MiniCssExtractPlugin.loader,css-loader,less-loader],}]},plugins: [new MiniCssExtractPlugin({filename: [name].[hash].css,chunkFilename: [id].css,})] }1.4.3 拆分多个css这里需要说的细一点,上面我们所用到的mini-css-extract-plugin会将所有的css样式合并为一个css文件。如果你想拆分为一一对应的多个css文件,我们需要使用到extract-text-webpack-plugin而目前mini-css-extract-plugin还不支持此功能。我们需要安装next版本的extract-text-webpack-pluginnpm i -D extract-text-webpack-pluginnext // webpack.config.jsconst path require(path); const ExtractTextWebpackPlugin require(extract-text-webpack-plugin) let indexLess new ExtractTextWebpackPlugin(index.less); let indexCss new ExtractTextWebpackPlugin(index.css); module.exports {module:{rules:[{test:/.css$/,use: indexCss.extract({use: [css-loader]})},{test:/.less$/,use: indexLess.extract({use: [css-loader,less-loader]})}]},plugins:[indexLess,indexCss] }1.5 打包 图片、字体、媒体、等文件file-loader就是将文件在进行一些处理后主要是处理文件名和路径、解析文件url并将文件移动到输出的目录中url-loader 一般与file-loader搭配使用功能与 file-loader 类似如果文件小于限制的大小。则会返回 base64 编码否则使用 file-loader 将文件移动到输出的目录中// webpack.config.js module.exports {// 省略其它配置 ...module: {rules: [// ...{test: /.(jpe?g|png|gif)$/i, //图片文件use: [{loader: url-loader,options: {limit: 10240,fallback: {loader: file-loader,options: {name: img/[name].[hash:8].[ext]}}}}]},{test: /.(mp4|webm|ogg|mp3|wav|flac|aac)(?.*)?$/, //媒体文件use: [{loader: url-loader,options: {limit: 10240,fallback: {loader: file-loader,options: {name: media/[name].[hash:8].[ext]}}}}]},{test: /.(woff2?|eot|ttf|otf)(?.*)?$/i, // 字体use: [{loader: url-loader,options: {limit: 10240,fallback: {loader: file-loader,options: {name: fonts/[name].[hash:8].[ext]}}}}]},]} }1.6 用babel转义js文件为了使我们的js代码兼容更多的环境我们需要安装依赖npm i babel-loader babel/preset-env babel/core注意babel-loader与babel-core的版本对应关系babel-loader 8.x 对应babel-core 7.xbabel-loader 7.x 对应babel-core 6.x 配置如下// webpack.config.js module.exports {// 省略其它配置 ...module:{rules:[{test:/.js$/,use:{loader:babel-loader,options:{presets:[babel/preset-env]}},exclude:/node_modules/},]} }上面的babel-loader只会将 ES6/7/8语法转换为ES5语法但是对新api并不会转换 例如(promise、Generator、Set、Maps、Proxy等)此时我们需要借助babel-polyfill来帮助我们转换npm i babel/polyfill // webpack.config.js const path require(path) module.exports {entry: [babel/polyfill,path.resolve(__dirname,../src/index.js)], // 入口文件 }手动把上面的demo敲一遍对阅读下面的文章更有益建议入门的同学敲三遍以上上面的实践是我们对webpack的功能有了一个初步的了解但是要想熟练应用于开发中我们需要一个系统的实战。让我们一起摆脱脚手架尝试自己搭建一个vue开发环境 2. 搭建vue开发环境上面的小例子已经帮助而我们实现了打包css、图片、js、html等文件。但是我们还需要以下几种配置2.1 解析.vue文件npm i -D vue-loader vue-template-compiler vue-style-loader npm i -S vuevue-loader 用于解析.vue文件vue-template-compiler 用于编译模板配置如下const vueLoaderPlugin require(vue-loader/lib/plugin) module.exports {module:{rules:[{test:/.vue$/,use:[vue-loader]},]},resolve:{alias:{vue$:vue/dist/vue.runtime.esm.js, :path.resolve(__dirname,../src)},extensions:[*,.js,.json,.vue]},plugins:[new vueLoaderPlugin()] }2.2 配置webpack-dev-server进行热更新npm i -D webpack-dev-server配置如下const Webpack require(webpack) module.exports {// ...省略其他配置devServer:{port:3000,hot:true,contentBase:../dist},plugins:[new Webpack.HotModuleReplacementPlugin()] }完整配置如下// webpack.config.js const path require(path); const {CleanWebpackPlugin} require(clean-webpack-plugin) const HtmlWebpackPlugin require(html-webpack-plugin) const MiniCssExtractPlugin require(mini-css-extract-plugin); const ExtractTextWebpackPlugin require(extract-text-webpack-plugin) const vueLoaderPlugin require(vue-loader/lib/plugin) const Webpack require(webpack) module.exports {mode:development, // 开发模式entry: {main:path.resolve(__dirname,../src/main.js),}, output: {filename: [name].[hash:8].js, // 打包后的文件名称path: path.resolve(__dirname,../dist) // 打包后的目录},module:{rules:[{test:/.vue$/,use:[vue-loader]},{test:/.js$/,use:{loader:babel-loader,options:{presets:[[babel/preset-env]]}}},{test:/.css$/,use: [vue-style-loader,css-loader,{loader:postcss-loader,options:{plugins:[require(autoprefixer)]}}]},{test:/.less$/,use: [vue-style-loader,css-loader,{loader:postcss-loader,options:{plugins:[require(autoprefixer)]}},less-loader]}]},resolve:{alias:{vue$:vue/dist/vue.runtime.esm.js, :path.resolve(__dirname,../src)},extensions:[*,.js,.json,.vue]},devServer:{port:3000,hot:true,contentBase:../dist},plugins:[new CleanWebpackPlugin(),new HtmlWebpackPlugin({template:path.resolve(__dirname,../public/index.html),filename:index.html}),new vueLoaderPlugin(),new Webpack.HotModuleReplacementPlugin()] }2.3 配置打包命令打包文件已经配置完毕接下来让我们测试一下首先在src新建一个main.js新建一个App.vue新建一个public文件夹里面新建一个index.html执行npm run dev这时候如果浏览器出现Vue开发环境运行成功那么恭喜你已经成功迈出了第一步2.4 区分开发环境与生产环境实际应用到项目中我们需要区分开发环境与生产环境我们在原来webpack.config.js的基础上再新增两个文件webpack.dev.js 开发环境配置文件开发环境主要实现的是热更新,不要压缩代码完整的sourceMapwebpack.prod.js生产环境配置文件生产环境主要实现的是压缩代码、提取css文件、合理的sourceMap、分割代码 需要安装以下模块: npm i -D webpack-merge copy-webpack-plugin optimize-css-assets-webpack-plugin uglifyjs-webpack-pluginwebpack-merge 合并配置copy-webpack-plugin 拷贝静态资源optimize-css-assets-webpack-plugin 压缩cssuglifyjs-webpack-plugin 压缩jswebpack mode设置production的时候会自动压缩js代码。原则上不需要引入uglifyjs-webpack-plugin进行重复工作。但是optimize-css-assets-webpack-plugin压缩css的同时会破坏原有的js压缩所以这里我们引入uglifyjs进行压缩2.4.1 webpack.config.jsconst path require(path) const {CleanWebpackPlugin} require(clean-webpack-plugin) const HtmlWebpackPlugin require(html-webpack-plugin) const vueLoaderPlugin require(vue-loader/lib/plugin) const MiniCssExtractPlugin require(mini-css-extract-plugin) const devMode process.argv.indexOf(--modeproduction) -1; module.exports {entry:{main:path.resolve(__dirname,../src/main.js)},output:{path:path.resolve(__dirname,../dist),filename:js/[name].[hash:8].js,chunkFilename:js/[name].[hash:8].js},module:{rules:[{test:/.js$/,use:{loader:babel-loader,options:{presets:[babel/preset-env]}},exclude:/node_modules/},{test:/.vue$/,use:[cache-loader,thread-loader,{loader:vue-loader,options:{compilerOptions:{preserveWhitespace:false}}}]},{test:/.css$/,use:[{loader: devMode ? vue-style-loader : MiniCssExtractPlugin.loader,options:{publicPath:../dist/css/,hmr:devMode}},css-loader,{loader:postcss-loader,options:{plugins:[require(autoprefixer)]}}]},{test:/.less$/,use:[{loader:devMode ? vue-style-loader : MiniCssExtractPlugin.loader,options:{publicPath:../dist/css/,hmr:devMode}},css-loader,less-loader,{loader:postcss-loader,options:{plugins:[require(autoprefixer)]}}]},{test:/.(jep?g|png|gif)$/,use:{loader:url-loader,options:{limit:10240,fallback:{loader:file-loader,options:{name:img/[name].[hash:8].[ext]}}}}},{test:/.(mp4|webm|ogg|mp3|wav|flac|aac)(?.*)?$/,use:{loader:url-loader,options:{limit:10240,fallback:{loader:file-loader,options:{name:media/[name].[hash:8].[ext]}}}}},{test:/.(woff2?|eot|ttf|otf)(?.*)?$/i,use:{loader:url-loader,options:{limit:10240,fallback:{loader:file-loader,options:{name:media/[name].[hash:8].[ext]}}}}}]},resolve:{alias:{vue$:vue/dist/vue.runtime.esm.js, :path.resolve(__dirname,../src)},extensions:[*,.js,.json,.vue]},plugins:[new CleanWebpackPlugin(),new HtmlWebpackPlugin({template:path.resolve(__dirname,../public/index.html)}),new vueLoaderPlugin(),new MiniCssExtractPlugin({filename: devMode ? [name].css : [name].[hash].css,chunkFilename: devMode ? [id].css : [id].[hash].css})] }2.4.2 webpack.dev.jsconst Webpack require(webpack) const webpackConfig require(./webpack.config.js) const WebpackMerge require(webpack-merge) module.exports WebpackMerge(webpackConfig,{mode:development,devtool:cheap-module-eval-source-map,devServer:{port:3000,hot:true,contentBase:../dist},plugins:[new Webpack.HotModuleReplacementPlugin()] })2.4.3 webpack.prod.jsconst path require(path) const webpackConfig require(./webpack.config.js) const WebpackMerge require(webpack-merge) const CopyWebpackPlugin require(copy-webpack-plugin) const OptimizeCssAssetsPlugin require(optimize-css-assets-webpack-plugin) const UglifyJsPlugin require(uglifyjs-webpack-plugin) module.exports WebpackMerge(webpackConfig,{mode:production,devtool:cheap-module-source-map,plugins:[new CopyWebpackPlugin([{from:path.resolve(__dirname,../public),to:path.resolve(__dirname,../dist)}]),],optimization:{minimizer:[new UglifyJsPlugin({//压缩jscache:true,parallel:true,sourceMap:true}),new OptimizeCssAssetsPlugin({})],splitChunks:{chunks:all,cacheGroups:{libs: {name: chunk-libs,test: /[/]node_modules[/]/,priority: 10,chunks: initial // 只打包初始时依赖的第三方}}}} })2.5 优化webpack配置看到这里你或许有些累了但是要想获取更好的offer,更高的薪水下面必须继续深入优化配置对我们来说非常有实际意义这实际关系到你打包出来文件的大小打包的速度等。具体优化可以分为以下几点2.5.1 优化打包速度构建速度指的是我们每次修改代码后热更新的速度以及发布前打包文件的速度。2.5.1.1 合理的配置mode参数与devtool参数mode可设置development production两个参数如果没有设置webpack4 会将 mode 的默认值设置为 productionproduction模式下会进行tree shaking(去除无用代码)和uglifyjs(代码压缩混淆)2.5.1.2 缩小文件的搜索范围(配置include exclude alias noParse extensions)alias: 当我们代码中出现 import vue时 webpack会采用向上递归搜索的方式去node_modules 目录下找。为了减少搜索范围我们可以直接告诉webpack去哪个路径下查找。也就是别名(alias)的配置。include exclude 同样配置include exclude也可以减少webpack loader的搜索转换时间。noParse 当我们代码中使用到import jq from jquery时webpack会去解析jq这个库是否有依赖其他的包。但是我们对类似jquery这类依赖库一般会认为不会引用其他的包(特殊除外,自行判断)。增加noParse属性,告诉webpack不必解析以此增加打包速度。extensions webpack会根据extensions定义的后缀查找文件(频率较高的文件类型优先写在前面)2.5.1.3 使用HappyPack开启多进程Loader转换在webpack构建过程中实际上耗费时间大多数用在loader解析转换以及代码的压缩中。日常开发中我们需要使用Loader对jscss图片字体等文件做转换操作并且转换的文件数据量也是非常大。由于js单线程的特性使得这些转换操作不能并发处理文件而是需要一个个文件进行处理。HappyPack的基本原理是将这部分任务分解到多个子进程中去并行处理子进程处理完成后把结果发送到主进程中从而减少总的构建时间npm i -D happypack2.5.1.4 使用webpack-parallel-uglify-plugin 增强代码压缩上面对于loader转换已经做优化那么下面还有另一个难点就是优化代码的压缩时间。npm i -D webpack-parallel-uglify-plugin2.5.1.5 抽离第三方模块对于开发项目中不经常会变更的静态依赖文件。类似于我们的elementUi、vue全家桶等等。因为很少会变更所以我们不希望这些依赖要被集成到每一次的构建逻辑中去。 这样做的好处是每次更改我本地代码的文件的时候webpack只需要打包我项目本身的文件代码而不会再去编译第三方库。以后只要我们不升级第三方包的时候那么webpack就不会对这些库去打包这样可以快速的提高打包的速度。这里我们使用webpack内置的DllPlugin DllReferencePlugin进行抽离在与webpack配置文件同级目录下新建webpack.dll.config.js代码如下// webpack.dll.config.js const path require(path); const webpack require(webpack); module.exports {// 你想要打包的模块的数组entry: {vendor: [vue,element-ui] },output: {path: path.resolve(__dirname, static/js), // 打包后文件输出的位置filename: [name].dll.js,library: [name]_library // 这里需要和webpack.DllPlugin中的name: [name]_library,保持一致。},plugins: [new webpack.DllPlugin({path: path.resolve(__dirname, [name]-manifest.json),name: [name]_library, context: __dirname})] };在package.json中配置如下命令dll: webpack --config build/webpack.dll.config.js接下来在我们的webpack.config.js中增加以下代码module.exports {plugins: [new webpack.DllReferencePlugin({context: __dirname,manifest: require(./vendor-manifest.json)}),new CopyWebpackPlugin([ // 拷贝生成的文件到dist目录 这样每次不必手动去cv{from: static, to:static}]),] };执行npm run dll会发现生成了我们需要的集合第三地方代码的vendor.dll.js我们需要在html文件中手动引入这个js文件!DOCTYPE html html langen headmeta charsetUTF-8meta nameviewport contentwidthdevice-width, initial-scale1.0meta http-equivX-UA-Compatible contentieedgetitle老yuan/titlescript srcstatic/js/vendor.dll.js/script /head bodydiv idapp/div /body /html这样如果我们没有更新第三方依赖包就不必npm run dll。直接执行npm run dev npm run build的时候会发现我们的打包速度明显有所提升。因为我们已经通过dllPlugin将第三方依赖包抽离出来了。2.5.1.6 配置缓存我们每次执行构建都会把所有的文件都重复编译一遍这样的重复工作是否可以被缓存下来呢答案是可以的目前大部分 loader 都提供了cache 配置项。比如在 babel-loader 中可以通过设置cacheDirectory 来开启缓存babel-loader?cacheDirectorytrue 就会将每次的编译结果写进硬盘文件默认是在项目根目录下的node_modules/.cache/babel-loader目录内当然你也可以自定义p但如果 loader 不支持缓存呢我们也有方法,我们可以通过cache-loader 它所做的事情很简单就是 babel-loader 开启 cache 后做的事情将 loader 的编译结果写入硬盘缓存。再次构建会先比较一下如果文件较之前的没有发生变化则会直接使用缓存。使用方法如官方 demo 所示在一些性能开销较大的 loader 之前添加此 loader即可/pnpm i -D cache-loader2.5.2 优化打包文件体积打包的速度我们是进行了优化但是打包后的文件体积却是十分大造成了页面加载缓慢浪费流量等接下来让我们从文件体积上继续优化2.5.2.1 引入webpack-bundle-analyzer分析打包后的文件webpack-bundle-analyzer将打包后的内容束展示为方便交互的直观树状图让我们知道我们所构建包中真正引入的内容npm i -D webpack-bundle-analyzer接下来在package.json里配置启动命令analyz: NODE_ENVproduction npm_config_reporttrue npm run buildwindows请安装npm i -D cross-envanalyz: cross-env NODE_ENVproduction npm_config_reporttrue npm run build接下来npm run analyz浏览器会自动打开文件依赖图的网页2.5.2.3 externals按照官方文档的解释如果我们想引用一个库但是又不想让webpack打包并且又不影响我们在程序中以CMD、AMD或者window/global全局等方式进行使用那就可以通过配置Externals。这个功能主要是用在创建一个库的时候用的但是也可以在我们项目开发中充分使用 Externals的方式我们将这些不需要打包的静态资源从构建逻辑中剔除出去而使用 CDN的方式去引用它们。p有时我们希望我们通过script引入的库如用CDN的方式引入的jquery我们在使用时依旧用require的方式来使用但是却不希望webpack将它又编译进文件中。这里官网案例已经足够清晰明了大家有兴趣可以点击了解 /pwebpack官网案例如下scriptsrchttps://code.jquery.com/jquery-3.1.0.jsintegritysha256-slogkvB1K3VOkzAI8QITxV3VzpOnkeNVsKvtkYLMjfkcrossoriginanonymous /script module.exports {//...externals: {jquery: jQuery} }; import $ from jquery; $(.my-element).animate(/* ... */);2.5.2.3 Tree-shaking这里单独提一下tree-shaking,是因为这里有个坑。tree-shaking的主要作用是用来清除代码中无用的部分。目前在webpack4 我们设置mode为production的时候已经自动开启了tree-shaking。但是要想使其生效生成的代码必须是ES6模块。不能使用其它类型的模块如CommonJS之流。如果使用Babel的话这里有一个小问题因为Babel的预案preset默认会将任何模块类型都转译成CommonJS类型。修正这个问题也很简单在.babelrc文件或在webpack.config.js文件中设置modules false就好了// .babelrc {presets: [[babel/preset-env,{modules: false}]] }或者// webpack.config.jsmodule: {rules: [{test: /.js$/,use: {loader: babel-loader,options: {presets: [babel/preset-env, { modules: false }]}}exclude: /(node_modules)/}] }经历过上面两个系列的洗礼到现在我们成为了一名合格的webpack配置工程师。但是光拧螺丝自身的可替代性还是很高下面我们将深入webpack的原理中去3.手写webpack系列经历过上面两个部分我们已经可以熟练的运用相关的loader和plugin对我们的代码进行转换、解析。接下来我们自己手动实现loader与plugin使其在平时的开发中获得更多的乐趣。3.1 手写webpack loaderloader从本质上来说其实就是一个node模块。相当于一台榨汁机(loader)将相关类型的文件代码(code)给它。根据我们设置的规则经过它的一系列加工后还给我们加工好的果汁(code)。loader编写原则单一原则: 每个 Loader 只做一件事链式调用: Webpack 会按顺序链式调用每个 Loader统一原则: 遵循 Webpack 制定的设计规则和结构输入与输出均为字符串各个 Loader 完全独立即插即用在日常开发环境中为了方便调试我们往往会加入许多console打印。但是我们不希望在生产环境中存在打印的值。那么这里我们自己实现一个loader去除代码中的console知识点普及之AST。AST通俗的来说假设我们有一个文件a.js,我们对a.js里面的1000行进行一些操作处理,比如为所有的await 增加try catch,以及其他操作但是a.js里面的代码本质上来说就是一堆字符串。那我们怎么办呢那就是转换为带标记信息的对象(抽象语法树)我们方便进行增删改查。这个带标记的对象(抽象语法树)就是AST。这里推荐一篇不错的AST文章 AST快速入门npm i -D babel/parser babel/traverse babel/generator babel/typesbabel/parser 将源代码解析成 ASTbabel/traverse 对AST节点进行递归遍历生成一个便于操作、转换的path对象babel/generator 将AST解码生成js代码babel/types通过该模块对具体的AST节点进行进行增、删、改、查新建 drop-console.jsconst parser require(babel/parser) const traverse require(babel/traverse).default const generator require(babel/generator).default const t require(babel/types) module.exportsfunction(source){const ast parser.parse(source,{ sourceType: module})traverse(ast,{CallExpression(path){ if(t.isMemberExpression(path.node.callee) t.isIdentifier(path.node.callee.object, {name: console})){path.remove()}}})const output generator(ast, {}, source);return output.code }如何使用const path require(path) module.exports {mode:development,entry:path.resolve(__dirname,index.js),output:{filename:[name].[contenthash].js,path:path.resolve(__dirname,dist)},module:{rules:[{test:/.js$/,use:path.resolve(__dirname,drop-console.js)}]} }实际上在webpack4中已经集成了去除console功能在minimizer中可配置 去除console附上官网 如何编写一个loader3.2 手写webpack plugin在 Webpack 运行的生命周期中会广播出许多事件Plugin 可以监听这些事件在合适的时机通过Webpack提供的API改变输出结果。通俗来说一盘美味的 盐豆炒鸡蛋 需要经历烧油 炒制 调味到最后的装盘等过程而plugin相当于可以监控每个环节并进行操作比如可以写一个少放胡椒粉plugin,监控webpack暴露出的生命周期事件(调味)在调味的时候执行少放胡椒粉操作。那么它与loader的区别是什么呢上面我们也提到了loader的单一原则,loader只能一件事比如说less-loader,只能解析less文件plugin则是针对整个流程执行广泛的任务。一个基本的plugin插件结构如下class firstPlugin {constructor (options) {console.log(firstPlugin options, options)}apply (compiler) {compiler.plugin(done, compilation {console.log(firstPlugin)))} }module.exports firstPlugincompiler 、compilation是什么compiler 对象包含了 Webpack 环境所有的的配置信息。这个对象在启动 webpack 时被一次性建立并配置好所有可操作的设置包括 optionsloader 和 plugin。当在 webpack 环境中应用一个插件时插件将收到此 compiler 对象的引用。可以使用它来访问 webpack 的主环境。compilation对象包含了当前的模块资源、编译生成资源、变化的文件等。当运行webpack 开发环境中间件时每当检测到一个文件变化就会创建一个新的 compilation从而生成一组新的编译资源。compilation 对象也提供了很多关键时机的回调以供插件做自定义处理时选择使用。compiler和 compilation的区别在于 compiler代表了整个webpack从启动到关闭的生命周期而compilation只是代表了一次新的编译过程compiler和compilation暴露出许多钩子我们可以根据实际需求的场景进行自定义处理compiler钩子文档compilation钩子文档下面我们手动开发一个简单的需求,在生成打包文件之前自动生成一个关于打包出文件的大小信息新建一个webpack-firstPlugin.jsclass firstPlugin{constructor(options){this.options options}apply(compiler){compiler.plugin(emit,(compilation,callback){let str for (let filename in compilation.assets){str 文件:${filename} 大小${compilation.assets[filename][size]()}n}// 通过compilation.assets可以获取打包后静态资源信息同样也可以写入资源compilation.assets[fileSize.md] {source:function(){return str},size:function(){return str.length}}callback()})} } module.exports firstPlugin如何使用const path require(path) const firstPlugin require(webpack-firstPlugin.js) module.exports {// 省略其他代码plugins:[new firstPlugin()] }执行 npm run build即可看到在dist文件夹中生成了一个包含打包文件信息的fileSize.md上面两个loader与plugin案例只是一个引导实际开发需求中的loader与plugin要考虑的方面很多建议大家自己多动手尝试一下。附上官网 如何编写一个plugin3.3 手写webpack由于篇幅过长且原理深入较多。鉴于本篇以快速上手应用于实际开发的原则这里决定另起一篇新的文章去详细剖析webpack原理以及实现一个demo版本。待格式校准后将会贴出文章链接在下方4. webpack5.0的时代无论是前端框架还是构建工具的更新速度远远超乎了我们的想象,前几年的jquery一把梭的时代一去不复返。我们要拥抱的是不断更新迭代的vue、react、node、serverless、docker、k8s....不甘落后的webpack也已经在近日发布了 webpack 5.0.0 beta 10 版本。在之前作者也曾提过webpack5.0旨在减少配置的复杂度使其更容易上手(webpack4的时候也说了这句话)以及一些性能上的提升使用持久化缓存提高构建性能使用更好的算法和默认值改进长期缓存long-term caching清理内部结构而不引入任何破坏性的变化引入一些breaking changes以便尽可能长的使用v5版本。目前来看维护者的更新很频繁相信用不了多久webpack5.0将会拥抱大众。感兴趣的同学可以先安装beta版本尝尝鲜。不过在此之前建议大家先对webpack4进行一番掌握,这样后面的路才会越来越好走。原作者姓名前端小布原出处segmentfault原文链接人类身份验证 - SegmentFault
http://www.huolong8.cn/news/96838/

相关文章:

  • 部署自己做的网站吗手机自适应网站建设维护
  • 阳狮做网站krypt免费wordpress空间
  • 做外贸去哪个网站找客户学平面设计网站
  • 网站开发流程管理xampp php网站模板
  • 彩票网站建设哪家公司好著名建站公司
  • 哪里有做空包网站的装修房子的步骤流程
  • 网站优化就是每天更新内容吗网站建设评审
  • 无忧网站建设哪家便宜注册公司网站的步骤
  • 不用代码可以做网站设计吗网站建设计划建议
  • 投标文件网站开发技术部分安徽理工大学新校区建设网站
  • 虚拟产品网站医院网站前置审批
  • 深圳网站建设服务哪家便宜网页框架代码
  • 做ps的赚钱的网站有哪些简单代码制作
  • 东莞seo建站优化收费淘宝代运营多少钱一个月
  • 网站怎么编辑有没有网站做字体变形
  • 网站排名seo培训金融代理平台代理加盟
  • 网站排名软件利搜品牌网站建设相关问题
  • 网站风格分类有哪些中学生制作网站
  • 单位网站中文域名到期续费上海网站建设网站
  • 河南智能网站建设平台淘宝客代理网站怎么做
  • 云南昆明做网站搜索引擎优化的实验结果分析
  • 有没有帮别人做图片的网站赚钱室内设计找工作网站
  • 福田附近公司做网站建设多少钱网站开发端
  • 网站上的充值链接怎么做百度代理
  • 做导航网站赚钱如何设计一个自己的网页
  • 网站用什么布局淄博网站网站建设
  • 自适应网站建设需要注意什么企业展厅的设计公司价格
  • 站长工具seo综合查询权重网络基础架构
  • 美食网站html代码站长权重
  • 一般网站用什么技术做的软装设计师年终总结