webpack.config.js 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. const {join, resolve} = require('path');
  2. const webpack = require('webpack');
  3. const glob = require('glob');
  4. const vuxLoader = require('vux-loader');
  5. const HtmlWebpackPlugin = require('html-webpack-plugin');
  6. const ExtractTextPlugin = require('extract-text-webpack-plugin');
  7. let entries = {};
  8. let chunks = [];
  9. let winMap = {};
  10. getEntriesAndChunks();
  11. let config = {
  12. entry: entries,
  13. output: {
  14. path: resolve(__dirname, './dist'),
  15. filename: '[name].js',
  16. publicPath: process.env.NODE_ENV === 'production' ? undefined : '/'
  17. },
  18. resolve: {
  19. //配置别名,在项目中可缩减引用路径
  20. extensions: ['.js', '.vue'],
  21. alias: {
  22. assets: join(__dirname, '/src/assets'),
  23. components: join(__dirname, '/src/components'),
  24. public: join(__dirname, '/src/public'),
  25. root: join(__dirname, 'node_modules')
  26. }
  27. },
  28. externals: [
  29. {api: "window.api"}
  30. ],
  31. module: {
  32. rules: [
  33. {
  34. test: /\.vue$/,
  35. loader: 'vue-loader'
  36. },
  37. {
  38. test: /\.js$/,
  39. use: 'babel-loader',
  40. exclude: /node_modules/
  41. },
  42. {
  43. test: /\.(less|css)$/,
  44. use: ['style-loader', 'css-loader', 'less-loader'],
  45. },
  46. {
  47. test: /\.html$/,
  48. use: [{
  49. loader: 'html-loader',
  50. options: {
  51. root: resolve(__dirname, 'src'),
  52. attrs: ['img:src', 'link:href']
  53. }
  54. }]
  55. },
  56. {
  57. test: /\.(png|jpe?g|gif|svg|svgz)(\?.+)?$/,
  58. exclude: /iconfont\.svg/,
  59. use: [{
  60. loader: 'url-loader',
  61. options: {
  62. limit: 10000,
  63. name: 'assets/img/[name].[ext]'
  64. }
  65. }]
  66. },
  67. {
  68. test: /\.(eot|woff|woff2|svg|ttf)([?]?.*)$/,
  69. use: 'file-loader'
  70. },
  71. {
  72. test: /muse-ui.src.*?js$/,
  73. use: 'babel-loader'
  74. }
  75. ]
  76. },
  77. plugins: [
  78. new ExtractTextPlugin({
  79. filename: '[name].css',
  80. allChunks: true
  81. }),
  82. new webpack.DefinePlugin({
  83. "webpackConfigParams":JSON.stringify({
  84. winMap: winMap
  85. })
  86. })
  87. ],
  88. devServer: {
  89. host: '192.168.0.141',
  90. port: 8010,
  91. historyApiFallback: false,
  92. noInfo: true,
  93. proxy: {
  94. '/api': {
  95. target: 'http://127.0.0.1:8010',
  96. changeOrigin: true,
  97. pathRewrite: {'^/api': ''}
  98. }
  99. },
  100. },
  101. devtool: '#eval-source-map'
  102. };
  103. const pages = getHtmls();
  104. pages.forEach(function (pathname) {
  105. // filename 用文件夹名字
  106. let firstSlashIndex = pathname.indexOf('/');
  107. let lastSlashIndex = pathname.lastIndexOf("/");
  108. let fileBasename = pathname.substring(firstSlashIndex + 1, lastSlashIndex);
  109. var conf = {
  110. filename: fileBasename + '.html', //生成的html存放路径,相对于path
  111. template: 'src/' + pathname + '.html', //html模板路径
  112. };
  113. var chunk = fileBasename;
  114. if (chunks.indexOf(chunk) > -1) {
  115. conf.inject = 'body';
  116. conf.chunks = ['common', chunk];
  117. }
  118. if (process.env.NODE_ENV === 'production') {
  119. conf.hash = true;
  120. }
  121. config.plugins.push(new HtmlWebpackPlugin(conf));
  122. });
  123. module.exports = vuxLoader.merge(config, {
  124. plugins: [
  125. {
  126. name: 'vux-ui'
  127. },
  128. {
  129. name: 'duplicate-style'
  130. },
  131. {
  132. name: 'less-theme',
  133. path: 'src/assets/css/vux-style-variable.less'
  134. }
  135. ]
  136. });
  137. function getEntriesAndChunks() {
  138. glob.sync('./src/pages/**/*.js').forEach(function (name) {
  139. let lastSlashIndex = name.lastIndexOf("/");
  140. var n = name.slice(name.lastIndexOf('src/') + 10, lastSlashIndex);
  141. entries[n] = [name];
  142. var winName = n.slice(n.lastIndexOf('/') + 1, n.length);
  143. if(!winMap[winName]) {
  144. winMap[winName] = n;
  145. }
  146. else {
  147. throw "页面名称重复:" + winName;
  148. }
  149. chunks.push(n);
  150. });
  151. }
  152. function getHtmls() {
  153. var htmls = [];
  154. glob.sync('./src/pages/**/*.html').forEach(function (name) {
  155. var n = name.slice(name.lastIndexOf('src/') + 4, name.length - 5);
  156. htmls.push(n);
  157. });
  158. return htmls;
  159. }
  160. if (process.env.NODE_ENV === 'production') {
  161. module.exports.devtool = '#source-map';
  162. module.exports.plugins = (module.exports.plugins || []).concat([
  163. new webpack.DefinePlugin({
  164. 'process.env': {
  165. NODE_ENV: '"production"'
  166. }
  167. }),
  168. new webpack.optimize.UglifyJsPlugin({
  169. compress: {
  170. warnings: false
  171. }
  172. })
  173. ]);
  174. }