基于 webpack2 实现的多入口项目脚手架详解


Posted in Javascript onJune 26, 2017

简介

基于 webpack2 实现的多入口项目脚手架,主要使用 extract-text-webpack-plugin 实现 js 、css 公共代码提取,html-webpack-plugin 实现 html 多入口,less-loader 实现 less 编译,postcss-loader 配置 autoprefixer 实现自动添加浏览器兼容前缀,html-withimg-loader 实现 html 内引入图片版本号添加和模板功能,babel-loader 实现 ES6 转码功能, happypack 多线程加速构建速度。

目录

├── dist   # 构建后的目录
├── config   # 项目配置文件
│ ├── webpack.config.js # webpack 配置文件
│ └── postcss.config.js # postcss 配置文件
├── src   # 程序源文件
│ └── js   # 入口
│ ├ └── index.js  # 匹配 view/index.html
│ ├ └── user  
│ ├ ├ ├── index.js # 匹配 view/user/index.html
│ ├ ├ ├── list.js # 匹配 view/user/list.html
│ ├ └── lib  # JS 库等,不参与路由匹配
│ ├ ├── jquery.js 
│ └── view   
│ ├ └── index.html # 对应 js/index.js
│ ├ └── user  
│ ├ ├── index.html # 对应 js/user/index.js
│ ├ ├── list.html # 对应 js/user/list.js
│ └── css   # css 文件目录
│ ├ └── base.css  
│ ├ └── iconfont.css 
│ └── font   # iconfont 文件目录
│ ├ └── iconfont.ttf  
│ ├ └── iconfont.css
│ └── img   # 图片文件目录
│ ├ └── pic1.jpg  
│ ├ └── pic2.png 
│ └── template  # html 模板目录
│ └── head.html  
│ └── foot.html

配置

多入口

根据 JS 目录获取多入口数组

const ROOT = process.cwd(); // 根目录

let entryJs = getEntry('./src/js/**/*.js');

/**
 * 根据目录获取入口
 * @param {[type]} globPath [description]
 * @return {[type]}  [description]
 */
function getEntry (globPath) {
 let entries = {};
 Glob.sync(globPath).forEach(function (entry) {
 let basename = path.basename(entry, path.extname(entry)),
 pathname = path.dirname(entry);
 // js/lib/*.js 不作为入口
 if (!entry.match(/\/js\/lib\//)) {
 entries[pathname.split('/').splice(3).join('/') + '/' + basename] = pathname + '/' + basename;
 }
 });
 return entries;
}

// webpack 配置
const config = {
 entry: entryJs,
 output: {
 filename: 'js/[name].js?[chunkhash:8]',
 chunkFilename: 'js/[name].js?[chunkhash:8]',
 path: path.resolve(ROOT, 'dist'),
 publicPath: '/'
 }, 
}

module

使用 babel 实现 ES2015 转 ES5,less 转 css 并使用 postcss 实现 autoprefixer 自动添加浏览器兼容,url-loader 实现 css 引用图片、字体添加版本号,html-withimg-loader 实现 html 引用图片添加版本号并实现模板功能。

module: {
 rules: [
 {
  test: /\.js$/,
  exclude: /(node_modules|bower_components)/,
  use: {
  loader: 'babel-loader?id=js',
  options: {
   presets: ['env']
  }
  }
 },
 {
  test: /\.(less|css)$/,
  use: ExtractTextPlugin.extract({
  fallback: 'style-loader?id=styles',
  use: [{
   loader: 'css-loader?id=styles',
   options: {
    minimize: !IsDev
   }
   }, 
   {
   loader: 'less-loader?id=styles'
   }, 
   {
   loader: 'postcss-loader?id=styles',
   options: {
    config: {
    path: PostcssConfigPath
    }
   }
   }
  ]
  })
 },
 {
  test: /\.(png|jpg|gif)$/,
  use: [
  {
   loader: 'url-loader',
   options: {
   limit: 100,
   publicPath: '',
   name: '/img/[name].[ext]?[hash:8]'
   }
  }
  ]
 },
 {
  test: /\.(eot|svg|ttf|woff)$/,
  use: [
  {
   loader: 'url-loader',
   options: {
   limit: 100,
   publicPath: '',
   name: '/font/[name].[ext]?[hash:8]'
   }
  }
  ]
 },
 // @see https://github.com/wzsxyz/html-withimg-loader
 {
  test: /\.(htm|html)$/i,
  loader: 'html-withimg-loader?min=false'
 }
 ]
},


// postcss.config.js
module.exports = {
 plugins: [
 require('autoprefixer')({
 browsers: ['> 1%', 'last 5 versions', 'not ie <= 9'],
 })
 ]
}

View 视图

根据目录对应关系,获取 js 对应的 html 入口

let entryHtml = getEntryHtml('./src/view/**/*.html'),
 configPlugins;

entryHtml.forEach(function (v) {
 configPlugins.push(new HtmlWebpackPlugin(v));
});

// webpack 配置
resolve: {
 alias: {
 views: path.resolve(ROOT, './src/view') 
 }
},

/**
 * 根据目录获取 Html 入口
 * @param {[type]} globPath [description]
 * @return {[type]}  [description]
 */
function getEntryHtml (globPath) {
 let entries = [];
 Glob.sync(globPath).forEach(function (entry) {
 let basename = path.basename(entry, path.extname(entry)),
 pathname = path.dirname(entry),
 // @see https://github.com/kangax/html-minifier#options-quick-reference
 minifyConfig = IsDev ? '' : {
 removeComments: true,
 collapseWhitespace: true,
 minifyCSS: true,
 minifyJS: true 
 };

 entries.push({
 filename: entry.split('/').splice(2).join('/'),
 template: entry,
 chunks: ['common', pathname.split('/').splice(3).join('/') + '/' + basename],
 minify: minifyConfig
 });

 });
 return entries;
}

plugins

使用 happypack 多线程加快构建速度,CommonsChunkPlugin 实现提取公用 js 为单独文件,extract-text-webpack-plugin 实现提取公用 css 为单独文件,

let configPlugins = [
 new HappyPack({
 id: 'js',
 // @see https://github.com/amireh/happypack
 threadPool: HappyThreadPool,
 loaders: ['babel-loader']
 }),
 new HappyPack({
 id: 'styles',
 threadPool: HappyThreadPool,
 loaders: ['style-loader', 'css-loader', 'less-loader', 'postcss-loader']
 }),
 new webpack.optimize.CommonsChunkPlugin({
 name: 'common'
 }),
 // @see https://github.com/webpack/webpack/tree/master/examples/multiple-entry-points-commons-chunk-css-bundle
 new ExtractTextPlugin({
 filename: 'css/[name].css?[contenthash:8]',
 allChunks: true
 })
];

entryHtml.forEach(function (v) {
 configPlugins.push(new HtmlWebpackPlugin(v));
});

// webpack 配置
plugins: configPlugins,

开发

webpack-dev-server 实现开发环境自动刷新等功能

// webpack 配置
devServer: {
 contentBase: [
 path.join(ROOT, 'src/')
 ],
 hot: false,
 host: '0.0.0.0',
 port: 8080
}

开发

npm start

http://localhost:8080/view

构建

cross-env 实现区分开发和生产环境构建

命令 说明

npm run dev 开发环境构建,不压缩代码

npm run build 生产环境构建,压缩代码

仓库:https://github.com/givebest/webpack2-multiple-entry

本地下载:http://xiazai.3water.com/201706/yuanma/webpack2-multiple-entry(3water.com).rar

总结

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

Javascript 相关文章推荐
可以把编码转换成 gb2312编码lib.UTF8toGB2312.js
Aug 21 Javascript
IE的有条件注释判定IE版本详解(附实例代码)
Jan 04 Javascript
idTabs基于JQuery的根据URL参数选择Tab插件
Apr 11 Javascript
JavaScript获取浏览器信息的方法
Nov 20 Javascript
Javascript使用uploadify来实现多文件上传
Nov 16 Javascript
JS 实现可停顿的垂直滚动实例代码
Nov 23 Javascript
微信小程序 数据遍历的实现
Apr 05 Javascript
纯JS实现出生日期[年月日]下拉菜单效果
Jun 01 Javascript
vue中使用input[type=&quot;file&quot;]实现文件上传功能
Sep 10 Javascript
基于Vue 实现一个中规中矩loading组件
Apr 03 Javascript
jquery3和layui冲突导致使用layui.layer.full弹出全屏iframe窗口时高度152px问题
May 12 jQuery
jQuery实现弹出层效果
Dec 10 jQuery
JavaScript的六种继承方式(推荐)
Jun 26 #Javascript
JavaScript数据类型和变量_动力节点Java学院整理
Jun 26 #Javascript
JavaScript基本语法_动力节点Java学院整理
Jun 26 #Javascript
JavaScript条件判断_动力节点Java学院整理
Jun 26 #Javascript
JavaScript脚本语言是什么_动力节点Java学院整理
Jun 26 #Javascript
JavaScript简介_动力节点Java学院整理
Jun 26 #Javascript
JavaScript数组_动力节点Java学院整理
Jun 26 #Javascript
You might like
无刷新动态加载数据 滚动条加载适合评论等页面
2013/10/16 PHP
php实现字符串首字母转换成大写的方法
2015/03/17 PHP
yii2.0实现验证用户名与邮箱功能
2015/12/22 PHP
Yii实现复选框批量操作实例代码
2017/03/15 PHP
15款优秀的jQuery导航菜单插件分享
2011/07/19 Javascript
jquery $(&quot;#variable&quot;) 循环改变variable的值示例
2014/02/23 Javascript
ajaxFileUpload.js插件支持多文件上传的方法
2014/09/02 Javascript
JavaScript中的原始值和复杂值
2016/01/07 Javascript
js数组的五种迭代方法及两种归并方法(推荐)
2016/06/14 Javascript
最原始的jQuery注册验证方式
2016/10/11 Javascript
jquery+css实现侧边导航栏效果
2017/06/12 jQuery
Vue 兄弟组件通信的方法(不使用Vuex)
2017/10/26 Javascript
在vue项目中引入高德地图及其UI组件的方法
2018/09/04 Javascript
axios 封装上传文件的请求方法
2018/09/26 Javascript
BootStrap模态框闪退问题实例代码详解
2018/12/10 Javascript
vue实现压缩图片预览并上传功能(promise封装)
2019/01/10 Javascript
Element-UI中Upload上传文件前端缓存处理示例
2019/02/21 Javascript
原生js实现密码强度验证功能
2020/03/18 Javascript
vue项目实现多语言切换的思路
2020/09/17 Javascript
[01:32]DOTA2次级联赛——首支职业女子战队选拔赛全记录
2014/10/23 DOTA
Python+Django在windows下的开发环境配置图解
2009/11/11 Python
详尽讲述用Python的Django框架测试驱动开发的教程
2015/04/22 Python
Python 查看文件的编码格式方法
2017/12/21 Python
Django objects的查询结果转化为json的三种方式的方法
2018/11/07 Python
Python基本数据结构之字典类型dict用法分析
2019/06/08 Python
详解Python3中setuptools、Pip安装教程
2019/06/18 Python
python用tkinter实现一个简易能进行随机点名的界面
2020/09/27 Python
Delphi软件工程师试题
2013/01/29 面试题
标准毕业生自荐信范文
2013/11/04 职场文书
学子宴答谢词
2014/01/25 职场文书
村干部四风问题整改措施
2014/09/30 职场文书
党员自我剖析材料范文
2014/10/06 职场文书
2014年教师思想工作总结
2014/12/03 职场文书
防溺水主题班会教案
2015/08/12 职场文书
礼仪培训心得体会
2016/01/22 职场文书
什么是执行力?9个故事告诉您:成功绝非偶然!
2019/07/05 职场文书