1. const path = require('path')
    2. function resolve(dir) {
    3. return path.join(__dirname, dir)
    4. }
    5. const BundleAnalyzerPlugin = require('webpack-bundle-analyzer')
    6. .BundleAnalyzerPlugin
    7. // 代码压缩
    8. const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
    9. // gzip压缩
    10. const CompressionWebpackPlugin = require('compression-webpack-plugin')
    11. const port = 3000 // dev port
    12. const proxy = {
    13. '/apis/': {
    14. target: 'http://192.168.110.218:2375',
    15. // secure: true,
    16. changeOrigin: true,
    17. pathRewrite: {
    18. // '^/proxy': '/'
    19. }
    20. },
    21. '/wechat/': {
    22. target: 'https://api.weixin.qq.com',
    23. secure: true,
    24. changeOrigin: true,
    25. pathRewrite: {
    26. '^/wechat': '/'
    27. }
    28. },
    29. '/abc/': {
    30. target: 'http://192.168.110.65:1010',
    31. // secure: true,
    32. changeOrigin: true,
    33. pathRewrite: {
    34. '^/abc': '/'
    35. }
    36. }
    37. }
    38. // cdn链接
    39. const cdn = {
    40. // cdn:模块名称和模块作用域命名(对应window里面挂载的变量名称)
    41. externals: {
    42. vue: 'Vue',
    43. vuex: 'Vuex',
    44. vant: 'vant',
    45. 'vue-router': 'VueRouter',
    46. axios: 'axios',
    47. moment: 'moment',
    48. 'vue-clipboard2': 'VueClipboard'
    49. },
    50. // cdncss链接
    51. css: [
    52. 'https://cdn.jsdelivr.net/npm/vant@2.12/lib/index.css'
    53. ],
    54. // cdnjs链接
    55. js: [
    56. 'https://cdn.jsdelivr.net/npm/vue@2.6.11/dist/vue.min.js',
    57. 'https://cdn.jsdelivr.net/npm/vuex@3.1.2/dist/vuex.min.js',
    58. 'https://unpkg.com/vue-router@3.2.0/dist/vue-router.min.js',
    59. 'https://cdn.jsdelivr.net/npm/vant@2.12/lib/vant.min.js',
    60. 'https://cdn.jsdelivr.net/npm/axios@0.21.1/dist/axios.min.js',
    61. 'https://cdn.jsdelivr.net/npm/moment@2.18.1/min/moment.min.js',
    62. 'https://cdn.jsdelivr.net/npm/vue-clipboard2@0.3.1/dist/vue-clipboard.min.js'
    63. ]
    64. }
    65. module.exports = {
    66. publicPath: process.env.NODE_ENV === 'development' ? '/' : '/qsbwechat/',
    67. outputDir: 'qsbwechat',
    68. assetsDir: 'static',
    69. indexPath: 'index.html',
    70. // filenameHashing: true, // 默认在生成的静态资源文件名中包含hash以控制缓存.
    71. lintOnSave: process.env.NODE_ENV === 'development', // 是否在开发环境下通过eslint-loader在每次保存时lint代码(在生产构建时禁用 eslint-loader).
    72. runtimeCompiler: false, // 是否使用包含运行时编译器的Vue构建版本.
    73. transpileDependencies: [], // Babel显式转译列表.
    74. productionSourceMap: process.env.NODE_ENV === 'development', // 如果你不需要生产环境的source map,可以将其设置为 false 以加速生产环境构建.
    75. crossorigin: '', // 设置生成的HTML中<link rel="stylesheet">和<script>标签的crossorigin属性(注:仅影响构建时注入的标签).
    76. integrity: false, // 在生成的HTML中的<link rel="stylesheet">和<script>标签上启用Subresource Integrity(SRI).
    77. devServer: {
    78. // 所有webpack-dev-server的选项都支持.
    79. proxy: proxy,
    80. port: port, // 端口
    81. disableHostCheck: true // 解决域名访问本地运行出现 Invalid Host Header 的问题
    82. },
    83. css: {
    84. // requireModuleExtension: false, // 当为true时,css文件名可省略module默认为false.
    85. extract: process.env.NODE_ENV !== 'development', // 默认生产环境下是true,开发环境下是false.
    86. sourceMap: false, // 是否为CSS开启source map.设置为true之后可能会影响构建的性能.
    87. loaderOptions: { // CSS相关的loader传递选项(支持:css-loader postcss-loader sass-loader less-loader stylus-loader).
    88. less: {
    89. // less-loader 版本小于 6.0,请移除 lessOptions 这一级,直接配置选项。
    90. // lessOptions: {
    91. // modifyVars: {
    92. // // 直接覆盖变量
    93. // 'text-color': '#111',
    94. // 'border-color': '#eee',
    95. // 'button-primary-background-color': '#d7b759'
    96. // // // 或者可以通过 less 文件覆盖(文件路径为绝对路径)
    97. // // hack: `true; @import "your-less-file-path.less";`
    98. // }
    99. // }
    100. }
    101. }
    102. },
    103. // 对内部的webpack配置(比如修改、增加Loader选项)(链式操作).
    104. chainWebpack: config => {
    105. console.log('chainWebpack',config);
    106. if (process.env.NODE_ENV !== 'development') {
    107. // const analyzer = new BundleAnalyzerPlugin({
    108. // analyzerPort: 9999
    109. // })
    110. // config.plugin('webpack-bundle-analyzer').use(analyzer)
    111. // csshansh
    112. config.plugin('extract-css').tap(args => [{
    113. filename: `css/[name].[contenthash:8].css`,
    114. chunkFilename: `css/[name].[contenthash:8].css`
    115. }])
    116. // ============注入cdn start============
    117. config.plugin('html').tap(args => {
    118. // 生产环境或本地需要cdn时,才注入cdn
    119. args[0].cdn = cdn
    120. return args
    121. })
    122. }
    123. config.resolve.alias
    124. .set('@', resolve('src'))
    125. .set('Sass', resolve('src/assets/sass'))
    126. .set('Img', resolve('src/assets/images'))
    127. .set('V', resolve('src/views'))
    128. config.module.rules.delete('svg')
    129. config.module
    130. .rule('svg-smart')
    131. .test(/\.svg$/)
    132. .include.add(resolve('src/assets/icons'))
    133. .end()
    134. .use('svg-sprite-loader')
    135. .loader('svg-sprite-loader')
    136. .options({
    137. symbolId: 'icon-[name]'
    138. })
    139. },
    140. // 如果这个值是一个对象,则会通过 webpack-merge 合并到最终的配置中.
    141. // 如果你需要基于环境有条件地配置行为,或者想要直接修改配置,那就换成一个函数(该函数会在环境变量被设置之后懒执行).该方法的第一个参数会收到已经解析好的配置.在函数内,你可以直接修改配置,或者返回一个将会被合并的对象.
    142. configureWebpack: config => {
    143. // cdn方式引入,则构建时要忽略相关资源
    144. if (process.env.NODE_ENV !== 'development') {
    145. config.externals = cdn.externals
    146. config.output.filename = `js/[name].[chunkhash:8].js`
    147. config.output.chunkFilename = `js/[name].[chunkhash:8].js`
    148. // 代码压缩
    149. config.plugins.push(
    150. new UglifyJsPlugin({
    151. uglifyOptions: {
    152. // 生产环境自动删除console
    153. compress: {
    154. // warnings: false, // 若打包错误,则注释这行
    155. drop_debugger: true,
    156. drop_console: true,
    157. pure_funcs: ['console.log']
    158. }
    159. },
    160. sourceMap: false,
    161. parallel: true
    162. })
    163. )
    164. // gzip压缩
    165. const productionGzipExtensions = ['html', 'js', 'css']
    166. config.plugins.push(
    167. new CompressionWebpackPlugin({
    168. filename: '[path].gz[query]',
    169. algorithm: 'gzip',
    170. test: new RegExp(
    171. '\\.(' + productionGzipExtensions.join('|') + ')$'
    172. ),
    173. threshold: 10240, // 只有大小大于该值的资源会被处理 10240
    174. minRatio: 0.8, // 只有压缩率小于这个值的资源才会被处理
    175. deleteOriginalAssets: false // 删除原文件
    176. })
    177. )
    178. // 公共代码抽离
    179. config.optimization = {
    180. splitChunks: {
    181. cacheGroups: {
    182. vendor: {
    183. chunks: 'all',
    184. test: /node_modules/,
    185. name: 'vendor',
    186. minChunks: 1,
    187. maxInitialRequests: 5,
    188. minSize: 0,
    189. priority: 100
    190. },
    191. common: {
    192. chunks: 'all',
    193. test: /[\\/]src[\\/]js[\\/]/,
    194. name: 'common',
    195. minChunks: 2,
    196. maxInitialRequests: 5,
    197. minSize: 0,
    198. priority: 60
    199. },
    200. styles: {
    201. name: 'styles',
    202. test: /\.(sa|sc|c)ss$/,
    203. chunks: 'all',
    204. enforce: true
    205. },
    206. runtimeChunk: {
    207. name: 'manifest'
    208. }
    209. }
    210. }
    211. }
    212. }
    213. config.performance = {
    214. // hints: 'warning', // 警告 webpack 的性能提示
    215. // maxEntrypointSize: 50000000, // 入口起点的最大体积
    216. // maxAssetSize: 30000000, // 生成文件的最大体积
    217. }
    218. }
    219. }