最近有个项目考虑SEO,所以必须做成多页面应用。为了保证开发速度和开发效率,决定使用webpack作为模块化的配置方案。下面主要针对一些重要的点提供思路,不做详细解释。我会把完整的代码放到github(项目地址)供大家参考。如果有什么优化,欢迎在评论区指出。内容|--构建webpack配置||--用于处理webpack配置的utils.js公共方法||--webpack.base.conf.js公共配置||--webpack.dev.conf.js开发环境配置||--webapck.prod.conf.js生产环境配置||--webpack.rules.conf.js文件处理规则|--dist存储变异文件|--||--src源文件||--资产||--页面|||--索引首页||||--index.html首页模板||||--index.js首页入口文件|处理多个html模板和对应的多个入口文件。html模板在项目根目录下创建一个htmlarrary.js存放页面配置://htmlarrary.jsmodule.exports=[{_html:'index',title:'Homepage',chunks:['index','manifest','vendors']//页面使用的vendor模块},{_html:'login',title:'login',chunks:['login']}]然后在/build/中创建getHtmlArray方法utils.js,使用来自动生成多个模板配置:///build/utils.jsconstHtmlWebpackPlugin=require('html-webpack-plugin')consthtmlArray=require('../htmlarray.js')exports.getHtmlArray=function(moduleExportsPlugins){//根据模板配置生成HtmlWebpackPluginconstgetHtmlConfig=function(name,chunks,title){return{template:`./src/pages/${name}/index.html`,filename:`./${name}.html`,favicon:'./src/assets/images/public/favicon.ico',title,inject:true,hash:true,//启用哈希块,//包缩小为由页面导入:process.env.NODE_ENV==='development'?false:{removeComments:true,//去除HTML中的注释collapseWhitespace:true,//折叠空白,即压缩代码rremoveAttributeQuotes:true,//删除属性引号},};};//循环创建模板配置htmlArray.forEach((element)=>{const{_html,chunks,title}=elementmoduleExportsPlugins.push(newHtmlWebpackPlugin(getHtmlConfig(_html,chunks,title)))})}Addmulti-在webpack.base.conf.js中通过getHtmlArray配置页面引擎:const{getHtmlArray}=require('./utils.js')module.exports={//...相关配置}getHtmlArray(module.exports.plugins)入口文件在/build/utils.js中创建getEntry方法自动生成入口文件的配置:///build/utils.jsconstglob=require('glob')exports.getEntry=function(){constentry={}//读取src目录中的所有页面条目glob.sync('./src/pages/*/*.js').forEach((name)=>{conststart=name.indexOf('src/')+4;constend=name.length-3;consteArr=[];constn=name.slice(start,end).split('/')[1];eArr.push(name);eArr。push('@babel/polyfill');//这个引入是为了使用asyncawait,可以支持一些IE不支持的属性rted,兼容entry[n]=eArr;})returnentry;}在webpack.base.conf.js中通过getEntry添加多个entryConfiguration://webpack.base.conf.jsconst{getEntry}=require('./utils.js')module.exports={entry:getEntry(),}JSJS对于JSJS,我们一般有如下需求:eslint错误提示;ts-loader解析typescript语法;babel-loader解析ES6语法针对以上需求,我们配置一些规则,做一些扩展://webpack.rules.conf.jsmodule.exports=[{test:/\.(js|ts)$/,exclude:/node_modules/,use:[{loader:'babel-loader',options:{presets:[['@babel/preset-env',{useBuiltIns:'usage',targets:{chrome:'58',ie:'8'},corejs:2}]]}},{loader:'ts-loader'},{loader:'eslint-loader',options:{cache:true//优化打包速度}}]}]在生产环境中,我们需要压缩js文件,提取公共代码,所以需要在webpack.prod.conf.js中进行优化://webpack.prod.conf.jscconstmerge=require('webpack-merge')constUglifyJsPlugin=require('uglifyjs-webpack-plugin')constbaseConfig=require('./webpack.base.conf.js')constprodConfig={optimization:{minimizer:[//会导致sourcemap消失newUglifyJsPlugin({uglifyOptions:({compress:false})}),newOptimizeCSSAssetsPlugin({})],splitChunks:{chunks:'all',cacheGroups:{vendors:{//提取第三方插件test:/[\\/]node_modules[\\/]/,//指定node_modules下的第三方包name:'vendors',priority:-10//提取优先级},utilCommon:{//提取自定义name:'common',minSize:0,//将引用模块分离成新代码文件的最小体积minChunks:2,//表示不同文件等引用模块被引用多少次才能分离生成新的chunkspriority:-20}}},//优化.runtimeChunk是告诉webpack是否单独打包这部分来优化缓存问题autoprefixer插件,自动兼容处理;sass-loader解析sass语法;MiniCssExtractPlugin执行css压缩针对以上需求,我们配置一些规则,做一些扩展://webpack.rules.conf.jsconstMiniCssExtractPlugin=require('mini-css-extract-plugin')module.exports=[{test:/\.scss$/i,use:[Object.assign(//生产环境需要使用MiniCssExtractPlugin.loader代替style-loader来压缩css{loader:process.env.NODE_ENV==='production'?MiniCssExtractPlugin.loader:'style-loader'},//解决css图片编译后无法正常显示的问题process.env.NODE_ENV==='production'?{options:{publicPath:'../'}}:{}),'css-loader','sass-loader','postcss-loader']}]在生产环境中,我们需要对css文件进行压缩,所以需要在webpack.prod.conf.js中进行优化://webpack.产品。conf.jscconstmerge=require('webpack-merge')constMiniCssExtractPlugin=require('mini-css-extract-plugin')constOptimizeCSSAssetsPlugin=require('optimize-css-assets-webpack-plugin')constbaseConfig=要求('./webpack.base.conf.js')constprodConfig={优化:{最小化:[新的OptimizeCSSAssetsPlugin({})],},插件:[newMiniCssExtractPlugin({filename:'css/[name].[contenthash:8].css',chunkFileName:'[id].[contenthash:8].css'}),]}module.exports=merge(baseConfig,prodConfig)imagesimages,我们一般有如下需求:可以解析css和js中的图片;html中img标签中的图片可以解析针对以上需求,我们配置一些规则,做一些扩展://webpack.rules.conf.jsconstMiniCssExtractPlugin=require('mini-css-extract-plugin')module.exports=[{test:/\.html$/,use:[//如果img标签的src为空,会报错xxxHTMLLINKxxx0.{loader:'html-loader',}]},{test:/\.(png|jpg|gif|ico)$/,使用:[{loader:'url-loader',options:{name:'[name].[hash:8].[ext]',limit:30000,outputPath:'./images'}}]}]otherdevserverandhotupdate//webpack.dev.conf.jsconstdevConfig={devServer:{open:true,host:'0.0.0.0',port:2000,useLocalIp:true,hot:true},plugins:[newwebpack.HotModuleReplacementPlugin()]}这样就智能启动了css热更新。如果需要js热更新,需要加一段代码。请自行查找官网文档。如果img标签的src为空,会报错xxxHTMLLINKxxx0。如果报错:TS2688:Cannotfindtypedefinitionfilefor'unist'。意思是需要安装@types/unist,报其他类似的错误。这是typescript@2.0替换types支持方法导致的错误。编译后css图片路径错误。根据是否是生产环境动态添加publicPath,点这里。
