0前言本文是对TCM项目的WebPack配置文件的总结。主要概述了一些常用的配置选项和插件的使用,对以后的项目有一定的指导意义。TCM的webpack配置文件包括三个基础文件:webapck.config.base.js、webapck.config.dev.js、webapck.config.prod.js,webpack.config.base.js是基础配置文件,webpack.config。dev.js是开发配置,webpack.config.prod.js是产品配置文件,webpack.config.base.js包含webpack.config.prod.js和webpack.config.base.js共享的一些基础配置,而webpack.config.prod.js和webpack.config.base.js在webpack.config.base.js的基础上增加了一些必要的配置。为了引入Node的expressAPI,通过dev.js和prod.js定义了顶层配置。因此,package.json文件的scripts部分定义了不同配置下开发的npm指令:以下是更多关于《入门Webpack,看这篇就够了》的总结,补充了很多网上搜集的资料,目的是为了更深入的了解TCM中的WebPack配置。1为什么要用webpack?Node.js的发展导致了各种依赖的出现,其中包括各种插件和加载器,可以简化开发过程。模块化是前端发展的一大趋势。基于React的单页应用完美诠释了模块化的理念。它是通过组件开发的,组件之间相互引用,引用外部依赖。为了打包外部依赖和本地的JavaScript模块、SCSS模块、图片等,打包工具应运而生。WebPack最著名,Gulp/Grunt也类似。webpack的优势之一是它将所有文件(包括CSS、HTML、图像和JavaScript代码)视为模块。只要在配置中包含相应的loader,就可以进行处理和打包。1.1WebPack与Grunt、Gulp相比有什么特点?事实上,Webpack和其他两者并没有太大的可比性。Gulp/Grunt是一个可以优化前端开发流程的工具,而WebPack是一个模块化的解决方案。但是,Webpack的优势使得Webpack成为Gulp/GruntGrunt-like工具的替代品。Grunt和Gulp的工作方式是:在一个配置文件中,指定执行某些文件的编译、组合、压缩等任务的具体步骤,然后这个工具就可以自动为你完成这些任务。Webpack的工作方式是:把你的项目当作一个整体,通过一个给定的主文件(比如:index.js),Webpack会从这个文件开始寻找你项目的所有依赖文件,使用loader来处理它们,然后最后打包为浏览器可读的JavaScript文件。2webpack配置文件常用配置项webpack有一个默认的配置文件webpack.config.js(官方文档),位于项目的根目录下,你也可以根据需要创建多个配置文件,TCMngr配置了三个文件:webpack.base.conf.js/webpack.dev.config.js/webpack.prod.conf.js。在package.json的scripts中添加不同的命令设置不同的配置文件,TCMngr的package.json中有“scripts”:{"start":"cross-envNODE_ENV=developmentnodebuild/dev.js","build":"cross-envNODE_ENV=productionnodebuild/prod.js"},可以看到这里使用了cross-env依赖包。该软件包允许以UNIX方式设置环境变量,并在Windows上正常运行。安装命令:npminstallcross-env--save-devwebpack配置文件本质上是一个JavaScript模块,可以使用JavaScript语言,该文件会导出一个配置对象,格式如下:mudule.exports={};所有的配置信息都在这里对象中体现,包括:entry:打包好的入口文件,可以是字符串也可以是对象。如果只有一个模块需要打包,使用这种形式;如果是对象,则打包该对象对应的所有文件。对象可以是包含多个打包模块的数组,依赖性强的排在最前面,也可以是键值对,对应不同的输出包,包名就是键名;TCM的webpack.base.conf.js指出需要打包的文件包括框架、类库、入口源码。resolve:影响模块解析的设置,它是一个包含以下属性的对象。resolve.extensions:自动识别文件扩展名,如果你想请求一个没有扩展名的js文件(如:require('index')),那么你需要在数组中加入'.js'。没有必要配置此选项。如果未配置,将使用默认值["",".webpack.js",".web.js",".js"]。手动设置将导致默认值被覆盖。如果您希望每个模块都根据自己的扩展名进行解析,请添加一个空字符串。resolve.modulesDirectories:目录名数组,会在本目录和本目录的顶层目录中查找依赖的模块。默认值为Default:["web_modules","node_modules"]。resolve.root:包含依赖模块的绝对路径,可以是一个目录数组output:打包后的输出结果是一个对象,包含以下属性:filename:输出文件名,filename中的[name]会被entry中的key替换;path:输出路径;publicpath:通过浏览器地址访问时的公共URL。module:定义模块的处理逻辑,是一个对象;loaders:定义了一系列用于自动加载的loader,是一个对象数组;[{test:正则表达式,用于匹配处理后的文件loader/loaders:stringorarray,表示使用的loader,loader:string表示使用!分隔的loader,loaders:[]表示使用的loader数组。include:包含的文件夹exclude:排除的文件夹}]plugins:定义插件,一个数组,定义所有使用的插件。externals:在实际开发中,当我们想在项目中需要一些其他的类库或API,但又不想将这些类库的源码打包时,这个是必须的。此时,我们可以通过配置externals参数来解决这个问题:这样我们就可以放心的在项目中使用这些API了:varjQuery=require("jquery");devtool:选择调试工具,常用eval-source-map//示例{devtool:"#inline-source-map"}3插件(Plugins)和一些工具包插件(Plugins)用于扩展Webpack功能,它们将在整个建设过程中发挥作用,并执行相关任务。Loader和Plugins经常被混淆,但实际上它们是完全不同的东西。可以说loader是用来在打包构建过程中处理源文件(JSX、Scss、Less..)的,一次一个,而插件不直接操作单个文件,它直接影响整个构建过程。要使用插件,我们需要通过npm安装它,然后我们要做的就是在webpack配置的plugins关键字部分添加一个插件实例(plugins是一个数组)。3.1webpack-dev-server一般安装在devDependency:npminstallwebpack-dev-server--save-dev安装完成后,使用webpack-dev-server在浏览器窗口观察输出,浏览器会自动打开root项目index.html文件所在目录,默认端口号为8080,完整地址为http://localhost:8080/。使用命令webpack-dev-server--hot--inline完成自动刷新。为了缩短命令,在package.json的脚本中添加如下语句:"build":"webpack-dev-server--hot--inline--config'webpack-dev-config.js'"--config设置默认的webpack配置文件。devserver作为webpack的配置选项之一,有如下配置选项,体现在webpack.config.js中:devServer:{contentBase:"./public",//本地服务器加载的页面所在目录colors:true,//终端中的输出是彩色的historyApiFallback:true,//不跳转inline:true//实时刷新}3.2SourceMaps(方便调试)WebPack生成sourcemaps,可以对应编译后的文件和源文件,这样编译后的代码可读性更强,也更容易调试。要配置sourcemaps,你需要配置devtool。它有以下四种不同的配置选项,每种都有自己的优点和缺点。说明如下:以上选项自上而下打包速度越来越快,但负面影响也越来越大,更快的构建速度带来的后果就是对打包文件的执行有一定的影响。eval-source-map在学习阶段和小型到中性项目中是一个不错的选择,但请记住仅在开发阶段使用它,如下配置module.exports={devtool:'eval-source-map',//Configure生成SourceMaps,选择合适的optionentry:__dirname+"/app/main.js",output:{path:__dirname+"/public",filename:"bundle.js"}}3.3Babel:compileES6JSXBabel工具包括babel-core/babel-loader/babel-preset-es2015/babel-preset-react,如果使用命令行,安装babel-cli。Babel的配置比较复杂,体现在webpack.config.js和.babelrc中。webpack.config.js会自动调用.babelrc中的配置选项。webpack.config.json将包含以下配置//webpack.config.js{test:/\.js$/,exclude:/node_modules/,loader:'babel'}//.babelrc{"presets":["react","es2015"]}3.4CSS-loaderwebpack提供了两个处理样式表的工具,css-loader和style-loader,两者处理不同的任务,css-loader使你可以使用@import和url(...)方法实现require()的功能,style-loader将所有计算好的样式添加到页面中。两者的结合可以让你将样式表嵌入到webpack打包的JS文件中。Sass和Less等预处理器是原生CSS的扩展。它们允许您使用CSS中不存在的变量、嵌套、混合、继承等特性来编写CSS。CSS预处理器可以将这些特殊类型的语句转换成浏览器可识别的CSS语句,在webpack中配置相关加载器后即可使用。常用的CSS处理加载器包括LessLoader、SassLoader和StylusLoader。//在TCM的开发环境中,直接嵌入CSS,支持热替换//自动添加前缀的autoprefixer插件config.module.loaders.push({test:/\.css$/,loader:'style!css!auto??prefixer'},{test:/\.less$/,loader:'style!css!less!auto??prefixer'},{test:/\.scss$/,loader:'style!css!sass!auto??prefixer'});3.5浏览器同步插件varBrowserSyncPlugin=require('browser-sync-webpack-plugin');config.plugins.push(newBrowserSyncPlugin({host:'127.0.0.1',port:9090,//浏览器监听addressproxy:'http://127.0.0.1:9000/',logConnections:false,notify:false},{reload:false}));3.6webpack的进度条插件需要在webpack配置中加入如下语句使用这个插件:varNyanProgressPlugin=require('nyan-progress-webpack-plugin');plugins:[newNyanProgressPlugin()]效果如下:3.7HtmlWebpackPlugin:自动生成HTML插件这个插件基于一个简单的模板帮你生成最终的Html5文件,它会自动引用你打包好的JS文件。每次编译都会在文件名中插入不同的散列。//安装npminstall--save-devhtml-webpack-plugin//webpack.config.jsvarHtmlWebpackPlugin=require('html-webpack-plugin');config.plugins.push(newHtmlWebpackPlugin({filename:'index.html',template:config.commonPath.indexHTML,//加载文件chunksSortMode:'auto'}));插件有很多设置参数:title:设置标题的名称filename:设置这个html模板的文件名:要使用的模块的路径inject:将模板注入到'body'中的哪个标签,favicon:在html中添加一个favicon'./images/favico.ico',minify:是否压缩{...}|falsehash:是否哈希truefalse,cache:是否缓存,showErrors:是否显示错误,chunks:目前不太了解修改组件代码后会自动刷新并实时预览修改后的效果.在webpack中实现HMR也非常简单。你只需要做两个配置:将HMR插件添加到webpack配置文件中;将“hot”参数添加到WebpackDevServer。但是配置这些之后,JS模块还是不能自动热加载。你还需要在你的JS模块中执行一个Webpack提供的API来实现热加载。这个API虽然不难用,但是如果是React模块,用我们已经很熟悉的Babel,可以更方便的实现函数热加载。Babel有一个名为react-transform-hrm的插件,它允许HMR在不对React模块进行额外配置的情况下工作。//webpack中的配置varwebpack=require('webpack');varHtmlWebpackPlugin=require('html-webpack-plugin');config.plugins.push(plugins:[newwebpack.HotModuleReplacementPlugin()//热加载插件]);//安装react-transform-hmrnpminstall--save-devbabel-plugin-react-transformreact-transform-hmr//Babel中的配置{"presets":["react","es2015"],"env“:{“开发”:{“插件”:[[”反应转换”,{“转换”:[{“转换”:“反应转换-hmr”,“导入”:[“反应”],“locals":["module"]}]}]]}}}3.9优化插件OccurenceOrderPlugin:为组件分配ID,通过该插件webpack可以分析出使用频率最高的模块并确定优先级,并为它们分配最小的IDUglifyJsPlugin:压缩JS代码;ExtractTextPlugin:分离CSS和JS文件
