const fs = require('fs')
|
const path = require('path')
|
const hash = require('hash-sum')
|
const loaderUtils = require('loader-utils')
|
|
const {
|
parse
|
} = require(require.resolve('@vue/component-compiler-utils', {
|
paths: [require.resolve('vue-loader')]
|
})) // 确保使用的与 vue-loader 一致
|
|
const {
|
getGlobalUsingComponentsCode
|
} = require('@dcloudio/uni-cli-shared/lib/pages')
|
|
const {
|
jsPreprocessOptions
|
} = require('@dcloudio/uni-cli-shared/lib/platform')
|
|
const preprocessor = require('@dcloudio/vue-cli-plugin-uni/packages/webpack-preprocess-loader/preprocess')
|
|
const traverse = require('@dcloudio/webpack-uni-mp-loader/lib/babel/global-component-traverse')
|
|
const genStylesCode = require('../../vue-loader/lib/codegen/styleInjection')
|
|
const {
|
parseComponents
|
} = require('./util')
|
|
function getDefineComponents ({
|
components
|
}) {
|
return components.map(({
|
name,
|
source
|
}) => `Vue.component('${name}',require('${source}').default)`)
|
}
|
|
const appVueFilePath = path.resolve(process.env.UNI_INPUT_DIR, 'App.vue')
|
|
function getStylesCode (loaderContext) {
|
if (!fs.existsSync(appVueFilePath)) {
|
return
|
}
|
const source = fs.readFileSync(appVueFilePath, 'utf8')
|
const {
|
minimize,
|
sourceMap,
|
rootContext,
|
resourcePath,
|
resourceQuery
|
} = loaderContext
|
|
const options = loaderUtils.getOptions(loaderContext) || {}
|
|
const filename = path.basename(resourcePath)
|
const context = rootContext || process.cwd()
|
const sourceRoot = path.dirname(path.relative(context, resourcePath))
|
const descriptor = parse({
|
source,
|
compiler: options.compiler,
|
filename,
|
sourceRoot,
|
needMap: sourceMap
|
})
|
|
// styles
|
let stylesCode = ''
|
if (descriptor.styles.length) {
|
const isProduction = options.productionMode || minimize || process.env.NODE_ENV === 'production'
|
|
const stringifyRequest = r => loaderUtils.stringifyRequest(loaderContext, r)
|
|
// module id for scoped CSS & hot-reload
|
const rawShortFilePath = path
|
.relative(context, resourcePath)
|
.replace(/^(\.\.[/\\])+/, '')
|
|
const shortFilePath = rawShortFilePath.replace(/\\/g, '/') + resourceQuery
|
|
const needsHotReload = false
|
|
const id = hash(
|
isProduction
|
? (shortFilePath + '\n' + source)
|
: shortFilePath
|
)
|
stylesCode = genStylesCode(
|
loaderContext,
|
descriptor.styles,
|
id,
|
resourcePath,
|
stringifyRequest,
|
needsHotReload,
|
true, // needs explicit injection?
|
'app-vue'
|
)
|
}
|
return stylesCode.replace(/main\.[jt]s/g, 'App.vue')
|
}
|
|
module.exports = function (source, map) {
|
// 需要执行一遍条件编译 source
|
if (source.indexOf('#ifdef') !== -1) {
|
source = preprocessor.preprocess(source, jsPreprocessOptions.context, {
|
type: jsPreprocessOptions.type
|
})
|
}
|
// 追加小程序全局自定义组件(仅v3)
|
source = getGlobalUsingComponentsCode() + source
|
const automatorCode = process.env.UNI_AUTOMATOR_WS_ENDPOINT
|
? 'import \'@dcloudio/uni-app-plus/dist/automator.view\''
|
: ''
|
this.callback(null,
|
`
|
// @ts-nocheck
|
import 'uni-pages?${JSON.stringify({ type: 'view' })}'
|
${automatorCode}
|
function initView(){
|
${getStylesCode(this)}
|
typeof injectStyles ==='function' && injectStyles()
|
${getDefineComponents(parseComponents(source, traverse)).join('\n')}
|
UniViewJSBridge.publishHandler('webviewReady')
|
}
|
if(typeof plus !== 'undefined'){
|
initView()
|
} else {
|
document.addEventListener('plusready',initView)
|
}
|
`,
|
map)
|
}
|