webpack配置的最佳实践分享


Posted in Javascript onApril 21, 2017

本文主要介绍了关于webpack配置的最佳实践,本文分享的实践具有以下的优势:

  • 使用happypack提升打包速度。
  • 使用MD5 hash可以生成文件版本,进行版本控制
  • 在非单页面的系统中支持多个入口的配置
  • 模板中可以利用htmlplugin输出一些配置性的信息
  • 支持devserver,支持本地json数据的mock

一、webpack最佳实践中的需求

     1.热加载

     2.语法校验

     3.js打包

     4.模板打包

二、解决方案

1.webpack.config.json

var path = require('path');
var fs = require('fs');
var exec = require('child_process').exec;
var HappyPack = require('happypack');
var merge = require('webpack-merge');
var webpack = require('webpack');
var WebpackMd5Hash = require('webpack-md5-hash');
var HtmlwebpackPlugin = require('html-webpack-plugin');
var ROOT_PATH = path.resolve(__dirname);
var APP_PATH = path.resolve(ROOT_PATH, 'app');
var BUILD_PATH = path.resolve(ROOT_PATH, __dirname+'/devserver/public');
//取出页面文件映射
function getHtmlPluginArr() {
 var data = JSON.parse(fs.readFileSync('entryconf.json', 'utf-8'));
 var pageList = data.pageList;
 var resultObj = {
 "pluginArr": [],
 "entryObj": {}
 };
 for (var index = 0; index < pageList.length; index++) {
 var element = pageList[index];
 var entry = element.entry;
 //通过对app.json中src的路径截取获得分发路径
 var filename = (function () {
 var filenameStr = entry.split("./app/page/")[1];
 return filenameStr.substr(0, filenameStr.lastIndexOf("."));
 })();
 var title = element.title;
 var extra = element.extra;
 resultObj.entryObj[filename] = entry;
 //利用路径一部分来进行HtmlwebpackPlugin的chunks
 resultObj.pluginArr.push(
 new HtmlwebpackPlugin({
  chunks: [filename], //当前页面js
  title: title,
  extra: extra,//包含页面额外的配置信息
  template: "app/" + "template.ejs",
  filename: 'views/'+filename + '.ejs',
  chunksSortMode: "dependency"//按chunks的顺序对js进行引入
 })
 );
 //HappyPack, loader多进程去处理文件
 resultObj.pluginArr.push(
 new HappyPack({ id: 'html' }),
 new HappyPack({ id: 'css' }),
 new HappyPack({ id: 'js' }),
 new HappyPack({ id: 'tpl' })
 );
 }
 return resultObj;
}
var appJsonObj = getHtmlPluginArr();
/**通用配置 */
var commonConfig = {
 entry: appJsonObj.entryObj,
 module: {
 loaders: [
 { test: /\.html$/, loader: "html?minimize=false", happy: {id: "html"} },
 { test: /\.json$/, loader: "json" },
 { test: /\.scss|\.css$/, loaders: ["style", "css", "sass"], happy: {id: "css"} },
 { test: /\.(?:jpg|gif|png)$/, loader: 'url?limit=10240&name=images/[name]-[hash:10].[ext]' },
 { test: /\.handlebars/, loader: "handlebars", query: { helperDirs: [APP_PATH + "/helper"] }, happy: {id: "tpl"} },
 { test: /\.js$|\.jsx$/, exclude: /(node_modules|bower_components)/, loader: 'babel', query: { presets: ['es2015'] }, happy: {id: "js"} },
 ]
 },
 output: {
 path: BUILD_PATH,
 filename: "js/[name].js"
 },
 externals: {
 "jquery": "jQuery"
 },
 //配置短路径引用
 resolve: {
 extensions: ['', '.js', '.json', '.scss','.vue'],
 alias: {
 vue : 'vue/dist/vue.js'
 }
 },
 plugins: appJsonObj.pluginArr,
 cache: true
}
module.exports = merge(commonConfig, {
 output: {
 publicPath: '/',
 path: BUILD_PATH,
 filename: "js/[name]-[chunkhash:10].js"
 },
 plugins: [
 new webpack.optimize.UglifyJsPlugin({ minimize: true }),
 new WebpackMd5Hash()
 ]
});

2.模板文件的配置:

<!DOCTYPE html>
<html>
<head>
 <meta charset="UTF-8">
 <title>
 <%= htmlWebpackPlugin.options.title || '上单'%>
 </title>
</head>
<body>
 <div id="main-container"></div>
 <% if (htmlWebpackPlugin.options.extra&&htmlWebpackPlugin.options.extra.js) {%>
 <% for(var i = 0;i < htmlWebpackPlugin.options.extra.js.length;i++){ %>
 <script src="<%= htmlWebpackPlugin.options.extra.js[i] %>"></script>
 <% } %>
 <% } %>
</body>
<script src="//cdn.bootcss.com/jquery/2.2.3/jquery.min.js"></script>
</html>

3.webpack.dev.config.json配置

var path = require('path');
var fs = require('fs');
var merge = require('webpack-merge');
var webpack = require('webpack');
var HtmlwebpackPlugin = require('html-webpack-plugin');
var OpenBrowserPlugin = require('open-browser-webpack-plugin');
var ROOT_PATH = path.resolve(__dirname);
var APP_PATH = path.resolve(ROOT_PATH, 'app');
var BUILD_PATH = path.resolve(ROOT_PATH, 'build');
var MODULE_PATH = path.resolve(ROOT_PATH, 'node_modules');
//取出页面文件映射
function getHtmlPluginArr() {
 var data = JSON.parse(fs.readFileSync('app/entries.json', 'utf-8'));
 var pageList = data.pageList;
 var resultObj = {
 "pluginArr": [],
 "entryObj": {}
 };
 for (var index = 0; index < pageList.length; index++) {
 var element = pageList[index];
 var src = element.entry;
 //通过对app.json中src的路径截取获得分发路径
 var dist = (function() {
 var s1 = src.split("./app/entries/")[1];
 var s2 = s1.substr(0, s1.lastIndexOf("/"));
 return s2;
 })();
 var title = element.title;
 var extra = element.extra;
 resultObj.entryObj[dist] = src;
 //利用路径一部分来进行HtmlwebpackPlugin的chunks
 resultObj.pluginArr.push(
 new HtmlwebpackPlugin({
 chunks: [dist], //当前页面js
 title: title,
 extra: extra,//包含页面额外的配置信息
 template: "app/" + "template.ejs",
 filename: dist + '.html',
 chunksSortMode: "dependency" //按chunks的顺序对js进行引入
 })
 );
 }
 return resultObj;
}
var appJsonObj = getHtmlPluginArr();
/**通用配置 */
var commonConfig = {
 entry: appJsonObj.entryObj,
 module: {
 loaders: [
 { test: /\.html$/, loader: "html?minimize=false" },
 { test: /\.json$/, loader: "json" },
 { test: /\.scss|\.css$/, loaders: ["style", "css", "sass"] },
 { test: /\.(?:jpg|gif|png)$/, loader: 'url?limit=10240&name=../images/[name]-[hash:10].[ext]' },
 { test: /\.handlebars/, loader: "handlebars" },
 { test: /\.js$/, exclude: /(node_modules|bower_components)/, loader: 'babel', query: { presets: ['es2015','stage-3','react'] } },
 { test: /\.jsx$/, exclude: /(node_modules|bower_components)/, loader: 'babel', query: { presets: ['react','stage-3','es2015']} }
 ]
 },
 output: {
 path: BUILD_PATH,
 filename: "js/[name].js"
 },
 externals: {
 "jquery": "jQuery"
 },
 //配置短路径引用
 resolve: {
 alias: {
 module: path.resolve(APP_PATH, 'module'),
 service: path.resolve(APP_PATH, "services"),
 component: path.resolve(APP_PATH, "components"),
 entries: path.resolve(APP_PATH, "entries"),
 routes: path.resolve(APP_PATH, "routes"),
 node_modules: path.resolve(ROOT_PATH, 'node_modules')
 },
 extensions: ['', '.js', '.jsx']
 },
 plugins: appJsonObj.pluginArr,
 devtool: "cheap-source-map",
 cache: true
}
//webpack-dev-server 提供的是内存级别的server,不会生成build的文件夹
//访问路径直接参照build下的路径 如http://127.0.0.1:8080/shop/updateShop.html
module.exports = merge(commonConfig, {
 devServer: {
 hot: true,
 inline: true,
 progress: true,
 host: process.env.HOST,
 port: "8808",
 proxy: {
 '/api/getLeftBar': {
 target: 'http://127.0.0.1:8808/mock',//dev
 secure: false
 },
 '/api/getIndexData': {
 target: 'http://127.0.0.1:8808/mock',//dev
 secure: false
 },
 '/api/getblogs': {
 target: 'http://127.0.0.1:8808/mock',//dev
 secure: false
 },
 '/panda/*': {
 target: 'http://10.4.233.139:8411/',//dev
 secure: false
 },
 //转发至本地mock
 '/page3/*': {
 target: 'http://127.0.0.1:8808',
 secure: false
 }
 }
 },
 plugins: [
 new webpack.HotModuleReplacementPlugin(),
 new OpenBrowserPlugin({
 url: 'http://127.0.0.1:8808/test.html'
 })
 ]
});

总结

以上就是关于webpack最佳配置的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
javascript web对话框与弹出窗口
Feb 22 Javascript
JavaScript快速检测浏览器对CSS3特性的支持情况
Sep 26 Javascript
jQuery学习笔记之jQuery原型属性和方法
Jun 09 Javascript
jQuery源码解读之hasClass()方法分析
Feb 20 Javascript
vue基于Vue2.0和高德地图的地图组件实例
Apr 28 Javascript
详解vue跨组件通信的几种方法
Jun 15 Javascript
sublime text配置node.js调试(图文教程)
Nov 23 Javascript
微信小程序实现图片懒加载的示例代码
Dec 13 Javascript
angular4 共享服务在多个组件中数据通信的示例
Mar 30 Javascript
vue 做移动端微信公众号采坑经验记录
Apr 26 Javascript
vue 弹框产生的滚动穿透问题的解决
Sep 21 Javascript
微信小程序获取地理位置及经纬度授权代码实例
Sep 18 Javascript
详解Vue.js 2.0 如何使用axios
Apr 21 #Javascript
ES6新特性四:变量的解构赋值实例
Apr 21 #Javascript
jQuery+pjax简单示例汇总
Apr 21 #jQuery
利用n工具轻松管理Node.js的版本
Apr 21 #Javascript
基于jQuery实现文字打印动态效果
Apr 21 #jQuery
ES6新特性三: Generator(生成器)函数详解
Apr 21 #Javascript
Cookies 和 Session的详解及区别
Apr 21 #Javascript
You might like
php字符串过滤与替换小结
2015/01/26 PHP
学习php设计模式 php实现访问者模式(Visitor)
2015/12/07 PHP
不错的新闻标题颜色效果
2006/12/10 Javascript
YUI 读码日记之 YAHOO.lang.is*
2008/03/22 Javascript
基于jquery的放大镜效果
2012/05/30 Javascript
使用node.js半年来总结的 10 条经验
2014/08/18 Javascript
javascript获取本机操作系统类型的方法
2015/08/13 Javascript
JS实现的最简Table选项卡效果
2015/10/14 Javascript
chrome调试javascript详解
2015/10/21 Javascript
JS实现响应鼠标点击动画渐变弹出层效果代码
2016/03/25 Javascript
Js+Ajax,Get和Post在使用上的区别小结
2016/06/08 Javascript
javaScript事件机制兼容【详细整理】
2016/07/23 Javascript
Javascript基础回顾之(二) js作用域
2017/01/31 Javascript
JS 插件dropload下拉刷新、上拉加载使用小结
2017/04/13 Javascript
BootStrap表单时间选择器详解
2017/05/09 Javascript
nodejs批量下载图片的实现方法
2017/05/19 NodeJs
JS实现点击复选框变更DIV显示状态的示例代码
2017/12/18 Javascript
JS实现为动态创建的元素添加事件操作示例
2018/03/17 Javascript
VUE中v-on:click事件中获取当前dom元素的代码
2018/08/22 Javascript
vue组件实践之可搜索下拉框功能
2018/11/25 Javascript
JQuery+Bootstrap 自定义全屏Loading插件的示例demo
2019/07/03 jQuery
Vue使用lodop实现打印小结
2019/07/06 Javascript
Angular进行简单单元测试的实现方法实例
2020/08/16 Javascript
python 生成图形验证码的方法示例
2018/11/11 Python
Python版名片管理系统
2018/11/30 Python
python批量修改ssh密码的实现
2019/08/08 Python
Python 2种方法求某个范围内的所有素数(质数)
2020/01/31 Python
科尔士百货公司官网:Kohl’s
2016/07/11 全球购物
教育专业个人求职信
2013/12/02 职场文书
考试作弊被抓检讨书
2014/01/10 职场文书
高中语文教学反思
2014/01/16 职场文书
家长会邀请书
2014/01/25 职场文书
2016春季幼儿园大班开学寄语
2015/12/03 职场文书
Springboot使用Spring Data JPA实现数据库操作
2021/06/30 Java/Android
用Python可视化新冠疫情数据
2022/01/18 Python
公历12个月名称的由来
2022/04/12 杂记