index.js 9.7 KB
Newer Older
fxy060608's avatar
fxy060608 已提交
1 2 3 4 5 6
const path = require('path')
const webpack = require('webpack')

const {
  parseEntry,
  getMainEntry,
fxy060608's avatar
fxy060608 已提交
7
  normalizePath,
fxy060608's avatar
fxy060608 已提交
8 9 10 11
  getPlatformExts,
  getPlatformCssnano
} = require('@dcloudio/uni-cli-shared')

fxy060608's avatar
fxy060608 已提交
12
const WebpackUniAppPlugin = require('../../packages/webpack-uni-app-loader/plugin/index')
fxy060608's avatar
fxy060608 已提交
13

fxy060608's avatar
fxy060608 已提交
14 15
const CustomModuleIdsPlugin = require('../../packages/webpack-custom-module-ids-plugin/index')

fxy060608's avatar
fxy060608 已提交
16
const modifyVueLoader = require('../vue-loader')
fxy060608's avatar
fxy060608 已提交
17

fxy060608's avatar
fxy060608 已提交
18
const {
fxy060608's avatar
fxy060608 已提交
19
  createTemplateCacheLoader
fxy060608's avatar
fxy060608 已提交
20
} = require('../cache-loader')
fxy060608's avatar
fxy060608 已提交
21

fxy060608's avatar
fxy060608 已提交
22
function createUniMPPlugin () {
23
  const WebpackUniMPPlugin = require('@dcloudio/webpack-uni-mp-loader/lib/plugin/index-new')
fxy060608's avatar
fxy060608 已提交
24 25 26 27
  return new WebpackUniMPPlugin()
}

function getProvides () {
fxy060608's avatar
fxy060608 已提交
28
  const uniPath = require('@dcloudio/uni-cli-shared/lib/platform').getMPRuntimePath()
fxy060608's avatar
fxy060608 已提交
29
  const uniCloudPath = path.resolve(__dirname, '../../packages/uni-cloud/dist/index.js')
fxy060608's avatar
fxy060608 已提交
30
  const provides = {
fxy060608's avatar
fxy060608 已提交
31 32
    uni: [uniPath, 'default'],
    uniCloud: [uniCloudPath, 'default']
fxy060608's avatar
fxy060608 已提交
33 34
  }

fxy060608's avatar
fxy060608 已提交
35 36 37 38 39
  if (process.env.UNI_USING_VUE3) {
    provides.uni = ['@dcloudio/uni-' + process.env.UNI_PLATFORM + '/dist/uni.api.esm.js', 'default']
    provides.createMiniProgramApp = [uniPath, 'createApp']
  }

fxy060608's avatar
fxy060608 已提交
40
  if (process.env.UNI_USING_COMPONENTS) {
fxy060608's avatar
fxy060608 已提交
41 42 43
    provides.createApp = [uniPath, 'createApp']
    provides.createPage = [uniPath, 'createPage']
    provides.createComponent = [uniPath, 'createComponent']
fxy060608's avatar
fxy060608 已提交
44 45 46 47 48 49
  }

  if (
    process.env.UNI_PLATFORM === 'app-plus' &&
    process.env.UNI_USING_V8
  ) {
fxy060608's avatar
fxy060608 已提交
50
    provides.__f__ = [path.resolve(__dirname, '../format-log.js'), 'default']
51

fxy060608's avatar
fxy060608 已提交
52
    const cryptoProvide = [path.resolve(__dirname, '../crypto.js'), 'default']
fxy060608's avatar
fxy060608 已提交
53
    provides.crypto = cryptoProvide
54 55
    provides['window.crypto'] = cryptoProvide
    provides['global.crypto'] = cryptoProvide
fxy060608's avatar
fxy060608 已提交
56 57 58 59 60 61 62 63
  }

  // TODO 目前依赖库 megalo 通过判断 wx 对象是否存在来识别平台做不同处理
  if (
    process.env.UNI_PLATFORM !== 'mp-qq' &&
    process.env.UNI_PLATFORM !== 'mp-weixin' &&
    process.env.UNI_PLATFORM !== 'app-plus'
  ) { // 非微信小程序,自动注入 wx 对象
fxy060608's avatar
fxy060608 已提交
64
    provides.wx = provides.uni
fxy060608's avatar
fxy060608 已提交
65 66 67 68
  }
  return provides
}

fxy060608's avatar
fxy060608 已提交
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
class PreprocessAssetsPlugin {
  apply (compiler) {
    compiler.hooks.emit.tap('PreprocessAssetsPlugin', compilation => {
      const assets = compilation.assets
      const hasVendor = assets['common/vendor.js']
      Object.keys(assets).forEach(name => {
        const extname = path.extname(name)
        if (extname !== '.js') {
          return
        }
        if (name.startsWith('common')) {
          return
        }
        const dirname = path.dirname(name)
        const runtimeJsCode = `require('${path.relative(dirname, 'common/runtime.js')}');`
        const vendorJsCode = hasVendor ? `require('${path.relative(dirname, 'common/vendor.js')}');` : ''
        const code = `${runtimeJsCode}${vendorJsCode}` + assets[name].source().toString()
        assets[name] = {
          size () {
            return Buffer.byteLength(code, 'utf8')
          },
          source () {
            return code
          }

        }
      })
      delete assets['common/main.js']
      delete assets['app.js']
      delete assets['app.json']
      delete assets['app.wxss']
      delete assets['project.config.json']
      console.log(Object.keys(assets))
    })
  }
}

function initSubpackageConfig (webpackConfig, vueOptions) {
  webpackConfig.node.set('global', false)
  webpackConfig.plugins.delete('hash-module-ids')
  // 与子包共享的模块
  const sharedModules = {
    'uni-mp-weixin/dist/index.js': 'uniWeixin',
    'mp-vue/dist/mp.runtime.esm.js': 'uniVue'
  }
  const sharedModulePaths = Object.keys(sharedModules)
  webpackConfig
    .plugin('custom-hash-module-ids')
    .use(CustomModuleIdsPlugin, [{
      prefix: process.env.UNI_SUBPACKGE,
      custom (libIdent) {
        if (!libIdent) {
          return
        }
        const normalizedLibIdent = normalizePath(libIdent)
        const name = sharedModulePaths.find(p => normalizedLibIdent.endsWith(p))
        if (name) {
          return sharedModules[name]
        }
      }
    }])
  if (process.env.UNI_SUBPACKGE !== 'main') { // 非主包
    process.env.UNI_OUTPUT_DIR = path.resolve(process.env.UNI_OUTPUT_DIR, process.env.UNI_SUBPACKGE)
    vueOptions.outputDir = process.env.UNI_OUTPUT_DIR
    webpackConfig.output.path(process.env.UNI_OUTPUT_DIR)
    webpackConfig.output.jsonpFunction('webpackJsonp_' + process.env.UNI_SUBPACKGE)
    webpackConfig.externals([
      function (context, request, callback) {
        if (request === 'vue') {
          return callback(null, 'root global["webpackMain"]["uniVue"]')
        }
        const normalizedRequest = normalizePath(request)
        const name = sharedModulePaths.find(p => normalizedRequest.endsWith(p))
        if (name) {
          return callback(null, `root global["webpackMain"]["${sharedModules[name]}"]`)
        }
        callback()
      }
    ])
  }
}

fxy060608's avatar
fxy060608 已提交
151 152 153 154
module.exports = {
  vueConfig: {
    parallel: false
  },
fxy060608's avatar
fxy060608 已提交
155
  webpackConfig (webpackConfig, vueOptions, api) {
fxy060608's avatar
fxy060608 已提交
156 157 158 159 160 161 162 163 164 165
    if (!webpackConfig.optimization) {
      webpackConfig.optimization = {}
    }
    // disable noEmitOnErrors
    webpackConfig.optimization.noEmitOnErrors = false

    webpackConfig.optimization.runtimeChunk = {
      name: 'common/runtime'
    }

fxy060608's avatar
fxy060608 已提交
166
    webpackConfig.optimization.splitChunks = require('../split-chunks')()
fxy060608's avatar
fxy060608 已提交
167 168 169

    parseEntry()

fxy060608's avatar
fxy060608 已提交
170
    const statCode = process.env.UNI_USING_STAT ? 'import \'@dcloudio/uni-stat\';' : ''
fxy060608's avatar
fxy060608 已提交
171

fxy060608's avatar
fxy060608 已提交
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
    let beforeCode = 'import \'uni-pages\';'

    if (process.env.UNI_SUBPACKGE === 'main') {
      const uniPath = require('@dcloudio/uni-cli-shared/lib/platform').getMPRuntimePath()
      beforeCode +=
        `import uniVue from 'vue';import * as uniWeixin from '${uniPath}';global['webpackMain']={uniVue,uniWeixin};`
    }

    const plugins = [
      new WebpackUniAppPlugin(),
      createUniMPPlugin(),
      new webpack.ProvidePlugin(getProvides())
    ]

    if (process.env.UNI_SUBPACKGE && process.env.UNI_SUBPACKGE !== 'main') {
      plugins.push(new PreprocessAssetsPlugin())
    }
fxy060608's avatar
fxy060608 已提交
189 190

    return {
fxy060608's avatar
fxy060608 已提交
191
      mode: process.env.NODE_ENV === 'production' ? 'production' : 'development',
fxy060608's avatar
fxy060608 已提交
192 193 194 195 196 197
      entry () {
        return process.UNI_ENTRY
      },
      output: {
        filename: '[name].js',
        chunkFilename: '[id].js',
fxy060608's avatar
fxy060608 已提交
198 199
        globalObject: process.env.UNI_PLATFORM === 'mp-alipay' ? 'my' : 'global'
        // sourceMapFilename: '../.sourcemap/' + process.env.UNI_PLATFORM + '/[name].js.map'
fxy060608's avatar
fxy060608 已提交
200 201 202
      },
      performance: {
        hints: false
fxy060608's avatar
fxy060608 已提交
203 204 205 206 207 208 209 210 211 212 213 214
      },
      resolve: {
        extensions: ['.nvue'],
        alias: { // 仅 mp-weixin
          'mpvue-page-factory': require.resolve(
            '@dcloudio/vue-cli-plugin-uni/packages/mpvue-page-factory')
        }
      },
      module: {
        rules: [{
          test: path.resolve(process.env.UNI_INPUT_DIR, getMainEntry()),
          use: [{
215
            loader: path.resolve(__dirname, '../../packages/wrap-loader'),
fxy060608's avatar
fxy060608 已提交
216 217
            options: {
              before: [
fxy060608's avatar
fxy060608 已提交
218
                beforeCode + require('../util').getAutomatorCode() + statCode
fxy060608's avatar
fxy060608 已提交
219 220 221
              ]
            }
          }, {
fxy060608's avatar
fxy060608 已提交
222 223 224 225 226 227 228 229 230 231 232
            loader: '@dcloudio/webpack-uni-mp-loader/lib/main'
          }]
        }, {
          resourceQuery: /vue&type=script/,
          use: [{
            loader: '@dcloudio/webpack-uni-mp-loader/lib/script'
          }]
        }, {
          resourceQuery: /vue&type=template/,
          use: [{
            loader: '@dcloudio/webpack-uni-mp-loader/lib/template'
233 234
          }, {
            loader: '@dcloudio/vue-cli-plugin-uni/packages/webpack-uni-app-loader/page-meta'
fxy060608's avatar
fxy060608 已提交
235
          }]
fxy060608's avatar
fxy060608 已提交
236
        }, createTemplateCacheLoader(api), {
fxy060608's avatar
fxy060608 已提交
237 238 239
          resourceQuery: [
            /lang=wxs/,
            /lang=filter/,
fxy060608's avatar
fxy060608 已提交
240
            /lang=sjs/,
fxy060608's avatar
fxy060608 已提交
241 242
            /blockType=wxs/,
            /blockType=filter/,
fxy060608's avatar
fxy060608 已提交
243
            /blockType=sjs/
fxy060608's avatar
fxy060608 已提交
244
          ],
fxy060608's avatar
fxy060608 已提交
245 246 247 248
          use: [{
            loader: require.resolve(
              '@dcloudio/vue-cli-plugin-uni/packages/webpack-uni-filter-loader')
          }]
fxy060608's avatar
fxy060608 已提交
249 250
        }]
      },
fxy060608's avatar
fxy060608 已提交
251
      plugins
fxy060608's avatar
fxy060608 已提交
252 253
    }
  },
fxy060608's avatar
fxy060608 已提交
254
  chainWebpack (webpackConfig, vueOptions, api) {
fxy060608's avatar
fxy060608 已提交
255 256 257 258 259 260 261
    if (process.env.UNI_PLATFORM === 'mp-baidu') {
      webpackConfig.module
        .rule('js')
        .exclude
        .add(/\.filter\.js$/)
    }

fxy060608's avatar
fxy060608 已提交
262
    const compilerOptions = process.env.UNI_USING_COMPONENTS ? {} : require('../mp-compiler-options')
fxy060608's avatar
fxy060608 已提交
263

264
    modifyVueLoader(webpackConfig, {}, compilerOptions, api)
fxy060608's avatar
fxy060608 已提交
265

fxy060608's avatar
fxy060608 已提交
266 267
    const styleExt = getPlatformExts().style

fxy060608's avatar
fxy060608 已提交
268 269
    webpackConfig.plugin('extract-css')
      .init((Plugin, args) => new Plugin({
fxy060608's avatar
fxy060608 已提交
270
        filename: '[name]' + styleExt
fxy060608's avatar
fxy060608 已提交
271 272
      }))

fxy060608's avatar
fxy060608 已提交
273 274 275 276
    if (
      process.env.NODE_ENV === 'production' &&
      process.env.UNI_PLATFORM !== 'app-plus'
    ) {
fxy060608's avatar
fxy060608 已提交
277
      const OptimizeCssnanoPlugin = require('../../packages/@intervolga/optimize-cssnano-plugin/index.js')
fxy060608's avatar
fxy060608 已提交
278
      webpackConfig.plugin('optimize-css')
fxy060608's avatar
fxy060608 已提交
279
        .init((Plugin, args) => new OptimizeCssnanoPlugin({
fxy060608's avatar
fxy060608 已提交
280
          sourceMap: false,
fxy060608's avatar
fxy060608 已提交
281 282 283
          filter (assetName) {
            return path.extname(assetName) === styleExt
          },
fxy060608's avatar
fxy060608 已提交
284 285 286
          cssnanoOptions: {
            preset: [
              'default',
fxy060608's avatar
fxy060608 已提交
287 288 289
              Object.assign({}, getPlatformCssnano(), {
                discardComments: true
              })
fxy060608's avatar
fxy060608 已提交
290 291 292 293 294 295
            ]
          }

        }))
    }

fxy060608's avatar
fxy060608 已提交
296 297 298 299
    if (process.env.UNI_SUBPACKGE) {
      initSubpackageConfig(webpackConfig, vueOptions)
    }

fxy060608's avatar
fxy060608 已提交
300 301 302 303 304 305
    webpackConfig.plugins.delete('hmr')
    webpackConfig.plugins.delete('html')
    webpackConfig.plugins.delete('copy')
    webpackConfig.plugins.delete('preload')
    webpackConfig.plugins.delete('prefetch')
  }
fxy060608's avatar
fxy060608 已提交
306
}