提交 8b212567 编写于 作者: fxy060608's avatar fxy060608

Merge branch 'feat-cli-cache' of https://github.com/dcloudio/uni-app into dev

const fs = require('fs')
const path = require('path')
const crypto = require('crypto')
/** /**
* 1.page-loader 缓存基础的 app.json page.json project.config.json * 1.page-loader 缓存基础的 app.json page.json project.config.json
* 2.main-loader 缓存 app.json 中的 usingComponents 节点 * 2.main-loader 缓存 app.json 中的 usingComponents 节点
* 3.script-loader 修改缓存 usingComponents 节点 * 3.script-loader 修改缓存 usingComponents 节点
* 5.webpack plugin 中获取被修改的 page.json,component.json 并 emitFile * 5.webpack plugin 中获取被修改的 page.json,component.json 并 emitFile
*/ */
const jsonFileMap = new Map() let jsonFileMap = new Map()
const changedJsonFileSet = new Set() const changedJsonFileSet = new Set()
const componentSet = new Set() let componentSet = new Set()
const pageSet = new Set() let pageSet = new Set()
let globalUsingComponents = Object.create(null) let globalUsingComponents = Object.create(null)
let appJsonUsingComponents = Object.create(null) let appJsonUsingComponents = Object.create(null)
...@@ -228,6 +231,27 @@ function getSpecialMethods (name) { ...@@ -228,6 +231,27 @@ function getSpecialMethods (name) {
return componentSpecialMethods[name] || [] return componentSpecialMethods[name] || []
} }
const pagesJsonPath = path.resolve(process.env.UNI_INPUT_DIR, 'pages.json')
const cacheTypes = ['babel-loader', 'css-loader', 'uni-template-compiler', 'vue-loader']
function clearCache () {
const fsExtra = require('fs-extra')
cacheTypes.forEach(cacheType => {
fsExtra.emptyDirSync(path.resolve(
process.env.UNI_CLI_CONTEXT,
'node_modules/.cache/' + cacheType + '/' + process.env.UNI_PLATFORM
))
})
}
function digest (str) {
return crypto
.createHash('md5')
.update(str)
.digest('hex')
}
module.exports = { module.exports = {
getPageSet () { getPageSet () {
return pageSet return pageSet
...@@ -235,6 +259,62 @@ module.exports = { ...@@ -235,6 +259,62 @@ module.exports = {
getJsonFileMap () { getJsonFileMap () {
return jsonFileMap return jsonFileMap
}, },
// 先简单处理,该方案不好,
// 后续为 pages-loader 增加 cache-loader,
// 然后其他修改 json 的地方也要定制 cache-loader
store () {
const filepath = path.resolve(
process.env.UNI_CLI_CONTEXT,
'node_modules/.cache/uni-pages-loader/' + process.env.UNI_PLATFORM,
digest(process.env.UNI_INPUT_DIR) + '.json'
)
const files = Array.from(jsonFileMap.entries())
const pages = Array.from(pageSet)
const components = Array.from(componentSet)
const methods = componentSpecialMethods
fs.writeFileSync(filepath, JSON.stringify({
mtimeMs: fs.statSync(pagesJsonPath).mtimeMs,
files,
pages,
components,
methods,
globalUsingComponents,
appJsonUsingComponents
}))
},
restore () {
const filepath = path.resolve(
process.env.UNI_CLI_CONTEXT,
'node_modules/.cache/uni-pages-loader/' + process.env.UNI_PLATFORM,
digest(process.env.UNI_INPUT_DIR) + '.json'
)
if (!fs.existsSync(filepath)) {
try {
clearCache()
} catch (e) {}
return
}
const mtimeMs = fs.statSync(pagesJsonPath).mtimeMs
const jsonCache = require(filepath)
if (jsonCache.mtimeMs !== mtimeMs) {
try {
clearCache()
} catch (e) {}
return
}
jsonFileMap = new Map(jsonCache.files)
pageSet = new Set(jsonCache.pages)
componentSet = new Set(jsonCache.components)
componentSpecialMethods = jsonCache.methods
globalUsingComponents = jsonCache.globalUsingComponents
appJsonUsingComponents = jsonCache.appJsonUsingComponents
// restore 时,所有 file 均触发 change
for (let name of jsonFileMap.keys()) {
changedJsonFileSet.add(name)
}
return true
},
getJsonFile, getJsonFile,
getPagesJson, getPagesJson,
getComponentSet, getComponentSet,
......
...@@ -109,6 +109,17 @@ at ${resourcePath}.vue:1`) ...@@ -109,6 +109,17 @@ at ${resourcePath}.vue:1`)
* ...暂时使用方案1 * ...暂时使用方案1
*/ */
if (options.emitFile) { if (options.emitFile) {
// cache
if (process.env.UNI_USING_CACHE) {
const oldEmitFile = options.emitFile
process.UNI_CACHE_TEMPLATES = {}
options.emitFile = function emitFile (name, content) {
const absolutePath = path.resolve(process.env.UNI_OUTPUT_DIR, name)
process.UNI_CACHE_TEMPLATES[absolutePath] = content
oldEmitFile(name, content)
}
}
if (options.updateSpecialMethods) { if (options.updateSpecialMethods) {
options.updateSpecialMethods(resourcePath, [...res.specialMethods]) options.updateSpecialMethods(resourcePath, [...res.specialMethods])
} }
......
...@@ -96,7 +96,7 @@ const rules = [{ ...@@ -96,7 +96,7 @@ const rules = [{
babelrc: false babelrc: false
} }
}, },
jsPreprocessorLoader jsPreprocessorLoader
], ],
exclude (modulePath) { exclude (modulePath) {
return excludeModuleReg.test(modulePath) && modulePath.indexOf('@dcloudio') === -1 return excludeModuleReg.test(modulePath) && modulePath.indexOf('@dcloudio') === -1
......
...@@ -6,7 +6,7 @@ const { ...@@ -6,7 +6,7 @@ const {
isInHBuilderX isInHBuilderX
} = require('@dcloudio/uni-cli-shared') } = require('@dcloudio/uni-cli-shared')
// override // nvue override
moduleAlias.addAlias('weex-styler', path.resolve(__dirname, 'packages/weex-styler')) moduleAlias.addAlias('weex-styler', path.resolve(__dirname, 'packages/weex-styler'))
moduleAlias.addAlias('weex-template-compiler', path.resolve(__dirname, 'packages/weex-template-compiler')) moduleAlias.addAlias('weex-template-compiler', path.resolve(__dirname, 'packages/weex-template-compiler'))
moduleAlias.addAlias('./compileTemplate', path.resolve(__dirname, moduleAlias.addAlias('./compileTemplate', path.resolve(__dirname,
...@@ -19,6 +19,20 @@ moduleAlias.addAlias('./templateLoader', (fromPath, request, alias) => { ...@@ -19,6 +19,20 @@ moduleAlias.addAlias('./templateLoader', (fromPath, request, alias) => {
} }
return request return request
}) })
// vue cache
if ( // 非 h5 ,非 v3,非 native
process.env.UNI_PLATFORM !== 'h5' &&
!process.env.UNI_USING_V3 &&
!process.env.UNI_USING_NATIVE
) {
moduleAlias.addAlias('./loaders/pitcher', (fromPath, request, alias) => {
if (fromPath.indexOf('vue-loader') !== -1) {
return path.resolve(__dirname, 'packages/vue-loader/lib/loaders/pitcher')
}
return request
})
}
if (isInHBuilderX) { if (isInHBuilderX) {
moduleAlias.addAlias('typescript', path.resolve(process.env.UNI_HBUILDERX_PLUGINS, moduleAlias.addAlias('typescript', path.resolve(process.env.UNI_HBUILDERX_PLUGINS,
'compile-typescript/node_modules/typescript')) 'compile-typescript/node_modules/typescript'))
......
const qs = require('querystring')
const loaderUtils = require('loader-utils')
const hash = require('hash-sum')
const selfPath = require.resolve('vue-loader/lib/index')
const templateLoaderPath = require.resolve('vue-loader/lib/loaders/templateLoader')
const stylePostLoaderPath = require.resolve('vue-loader/lib/loaders/stylePostLoader')
const isESLintLoader = l => /(\/|\\|@)eslint-loader/.test(l.path)
const isNullLoader = l => /(\/|\\|@)null-loader/.test(l.path)
const isCSSLoader = l => /(\/|\\|@)css-loader/.test(l.path)
const isCacheLoader = l => /(\/|\\|@)cache-loader/.test(l.path)
const isPitcher = l => l.path !== __filename
const isPreLoader = l => !l.pitchExecuted
const isPostLoader = l => l.pitchExecuted
const dedupeESLintLoader = loaders => {
const res = []
let seen = false
loaders.forEach(l => {
if (!isESLintLoader(l)) {
res.push(l)
} else if (!seen) {
seen = true
res.push(l)
}
})
return res
}
const shouldIgnoreCustomBlock = loaders => {
const actualLoaders = loaders.filter(loader => {
// vue-loader
if (loader.path === selfPath) {
return false
}
// cache-loader
if (isCacheLoader(loader)) {
return false
}
return true
})
return actualLoaders.length === 0
}
module.exports = code => code
// This pitching loader is responsible for intercepting all vue block requests
// and transform it into appropriate requests.
module.exports.pitch = function (remainingRequest) {
const options = loaderUtils.getOptions(this)
const { cacheDirectory, cacheIdentifier } = options
const query = qs.parse(this.resourceQuery.slice(1))
let loaders = this.loaders
// if this is a language block request, eslint-loader may get matched
// multiple times
if (query.type) {
// if this is an inline block, since the whole file itself is being linted,
// remove eslint-loader to avoid duplicate linting.
if (/\.vue$/.test(this.resourcePath)) {
loaders = loaders.filter(l => !isESLintLoader(l))
} else {
// This is a src import. Just make sure there's not more than 1 instance
// of eslint present.
loaders = dedupeESLintLoader(loaders)
}
}
// remove self
loaders = loaders.filter(isPitcher)
// do not inject if user uses null-loader to void the type (#1239)
if (loaders.some(isNullLoader)) {
return
}
const genRequest = loaders => {
// Important: dedupe since both the original rule
// and the cloned rule would match a source import request.
// also make sure to dedupe based on loader path.
// assumes you'd probably never want to apply the same loader on the same
// file twice.
// Exception: in Vue CLI we do need two instances of postcss-loader
// for user config and inline minification. So we need to dedupe baesd on
// path AND query to be safe.
const seen = new Map()
const loaderStrings = []
loaders.forEach(loader => {
const identifier = typeof loader === 'string'
? loader
: (loader.path + loader.query)
const request = typeof loader === 'string' ? loader : loader.request
if (!seen.has(identifier)) {
seen.set(identifier, true)
// loader.request contains both the resolved loader path and its options
// query (e.g. ??ref-0)
loaderStrings.push(request)
}
})
return loaderUtils.stringifyRequest(this, '-!' + [
...loaderStrings,
this.resourcePath + this.resourceQuery
].join('!'))
}
// Inject style-post-loader before css-loader for scoped CSS and trimming
if (query.type === `style`) {
const cssLoaderIndex = loaders.findIndex(isCSSLoader)
if (cssLoaderIndex > -1) {
const afterLoaders = loaders.slice(0, cssLoaderIndex + 1)
const beforeLoaders = loaders.slice(cssLoaderIndex + 1)
const request = genRequest([
...afterLoaders,
stylePostLoaderPath,
...beforeLoaders
])
// console.log(request)
return `import mod from ${request}; export default mod; export * from ${request}`
}
}
// for templates: inject the template compiler & optional cache
if (query.type === `template`) {
const path = require('path')
// fixed by xxxxxx
const cacheLoader = cacheDirectory && cacheIdentifier
? [`${require.resolve('cache-loader')}??uni-cache-loader-template-options`]
: []
const preLoaders = loaders.filter(isPreLoader)
const postLoaders = loaders.filter(isPostLoader)
const request = genRequest([
...cacheLoader,
...postLoaders,
templateLoaderPath + `??vue-loader-options`,
...preLoaders
])
// console.log(request)
// the template compiler uses esm exports
return `export * from ${request}`
}
// if a custom block has no other matching loader other than vue-loader itself
// or cache-loader, we should ignore it
if (query.type === `custom` && shouldIgnoreCustomBlock(loaders)) {
return ``
}
// When the user defines a rule that has only resourceQuery but no test,
// both that rule and the cloned rule will match, resulting in duplicated
// loaders. Therefore it is necessary to perform a dedupe here.
const request = genRequest(loaders)
return `import mod from ${request}; export default mod; export * from ${request}`
}
...@@ -2,8 +2,8 @@ const loaderUtils = require('loader-utils') ...@@ -2,8 +2,8 @@ const loaderUtils = require('loader-utils')
module.exports = function(content) { module.exports = function(content) {
this.cacheable && this.cacheable() this.cacheable && this.cacheable()
const vueLoaderOptions = this.loaders[0] const vueLoaderOptions = this.loaders.find(loader => loader.ident === 'vue-loader-options')
if (vueLoaderOptions.ident === 'vue-loader-options') { if (vueLoaderOptions) {
const params = loaderUtils.parseQuery(this.resourceQuery) const params = loaderUtils.parseQuery(this.resourceQuery)
if (params.recyclable) { if (params.recyclable) {
Object.assign(vueLoaderOptions.options.compilerOptions, { Object.assign(vueLoaderOptions.options.compilerOptions, {
......
...@@ -25,8 +25,8 @@ module.exports = (api, options) => { ...@@ -25,8 +25,8 @@ module.exports = (api, options) => {
require('./lib/options')(options) require('./lib/options')(options)
api.configureWebpack(require('./lib/configure-webpack')(platformOptions, manifestPlatformOptions, options)) api.configureWebpack(require('./lib/configure-webpack')(platformOptions, manifestPlatformOptions, options, api))
api.chainWebpack(require('./lib/chain-webpack')(platformOptions)) api.chainWebpack(require('./lib/chain-webpack')(platformOptions, api))
} }
module.exports.defaultModes = { module.exports.defaultModes = {
......
const fs = require('fs')
const path = require('path')
const mkdirp = require('mkdirp')
const BJSON = require('buffer-json')
const {
getPartialIdentifier
} = require('./util')
const directories = new Set()
function write (key, data, callback) {
const dirname = path.dirname(key)
// template,缓存 mp template
if (
data.remainingRequest.indexOf('vue&type=template') !== -1 &&
process.UNI_CACHE_TEMPLATES
) {
data['mpTemplates'] = process.UNI_CACHE_TEMPLATES
delete process.UNI_CACHE_TEMPLATES
}
const content = BJSON.stringify(data)
if (directories.has(dirname)) {
// for performance skip creating directory
fs.writeFile(key, content, 'utf-8', callback)
} else {
mkdirp(dirname, (mkdirErr) => {
if (mkdirErr) {
callback(mkdirErr)
return
}
directories.add(dirname)
fs.writeFile(key, content, 'utf-8', callback)
})
}
}
function read (key, callback) {
fs.readFile(key, 'utf-8', (err, content) => {
if (err) {
callback(err)
return
}
try {
const data = BJSON.parse(content)
const mpTemplates = data['mpTemplates']
if (mpTemplates) {
Object.keys(mpTemplates).forEach(name => {
fs.writeFileSync(name, mpTemplates[name], 'utf-8')
})
}
callback(null, data)
} catch (e) {
callback(e)
}
})
}
module.exports = {
createTemplateCacheLoader: function (api) {
return {
resourceQuery: /type=uni-cache-loader-template/,
use: [{
loader: 'cache-loader',
ident: 'uni-cache-loader-template-options',
options: Object.assign(api.genCacheConfig(
'uni-template-compiler/' + process.env.UNI_PLATFORM,
getPartialIdentifier()
), {
read,
write
})
}]
}
}
}
...@@ -4,11 +4,15 @@ const { ...@@ -4,11 +4,15 @@ const {
sassLoaderVersion sassLoaderVersion
} = require('@dcloudio/uni-cli-shared/lib/scss') } = require('@dcloudio/uni-cli-shared/lib/scss')
const {
getPartialIdentifier
} = require('./util')
function resolve (dir) { function resolve (dir) {
return path.resolve(__dirname, '..', dir) return path.resolve(__dirname, '..', dir)
} }
module.exports = function chainWebpack (platformOptions) { module.exports = function chainWebpack (platformOptions, api) {
const { const {
runByHBuilderX, // 使用 HBuilderX 运行 runByHBuilderX, // 使用 HBuilderX 运行
cssPreprocessOptions cssPreprocessOptions
...@@ -48,11 +52,22 @@ module.exports = function chainWebpack (platformOptions) { ...@@ -48,11 +52,22 @@ module.exports = function chainWebpack (platformOptions) {
const langRule = webpackConfig.module.rule(lang) const langRule = webpackConfig.module.rule(lang)
const loader = loaders[lang] const loader = loaders[lang]
cssTypes.forEach(type => { cssTypes.forEach(type => {
if (process.env.UNI_USING_CACHE) {
langRule.oneOf(type)
.use(`uniapp-cache-css`)
.loader('cache-loader')
.options(api.genCacheConfig(
'css-loader/' + process.env.UNI_PLATFORM,
getPartialIdentifier()
))
.before('css-loader')
}
langRule.oneOf(type) langRule.oneOf(type)
.use(`uniapp-preprocss`) .use(`uniapp-preprocss`)
.loader(resolve('packages/webpack-preprocess-loader')) .loader(resolve('packages/webpack-preprocess-loader'))
.options(cssPreprocessOptions) .options(cssPreprocessOptions)
.before('css-loader') // 在 css-loader 之后条件编译一次,避免 import 进来的 css 没有走条件编译 .before('css-loader') // 在 css-loader 之后条件编译一次,避免 import 进来的 css 没有走条件编译
if (loader) { // 在 scss,less,stylus 之前先条件编译一次 if (loader) { // 在 scss,less,stylus 之前先条件编译一次
langRule.oneOf(type) langRule.oneOf(type)
.use(`uniapp-preprocss-` + lang) .use(`uniapp-preprocss-` + lang)
...@@ -79,7 +94,7 @@ module.exports = function chainWebpack (platformOptions) { ...@@ -79,7 +94,7 @@ module.exports = function chainWebpack (platformOptions) {
}) })
} }
platformOptions.chainWebpack(webpackConfig) platformOptions.chainWebpack(webpackConfig, api)
// define // define
webpackConfig webpackConfig
.plugin('uni-define') .plugin('uni-define')
......
...@@ -6,6 +6,10 @@ const CopyWebpackPlugin = require('copy-webpack-plugin') ...@@ -6,6 +6,10 @@ const CopyWebpackPlugin = require('copy-webpack-plugin')
const merge = require('webpack-merge') const merge = require('webpack-merge')
const {
getPartialIdentifier
} = require('./util')
function resolve (dir) { function resolve (dir) {
return path.resolve(__dirname, '..', dir) return path.resolve(__dirname, '..', dir)
} }
...@@ -14,7 +18,7 @@ function resolveModule (dir) { ...@@ -14,7 +18,7 @@ function resolveModule (dir) {
return path.resolve(__dirname, '../../..', dir) return path.resolve(__dirname, '../../..', dir)
} }
module.exports = function configureWebpack (platformOptions, manifestPlatformOptions, vueOptions) { module.exports = function configureWebpack (platformOptions, manifestPlatformOptions, vueOptions, api) {
const { const {
runByHBuilderX, // 使用 HBuilderX 运行 runByHBuilderX, // 使用 HBuilderX 运行
isInHBuilderX, // 在 HBuilderX 的插件中 isInHBuilderX, // 在 HBuilderX 的插件中
...@@ -138,13 +142,19 @@ module.exports = function configureWebpack (platformOptions, manifestPlatformOpt ...@@ -138,13 +142,19 @@ module.exports = function configureWebpack (platformOptions, manifestPlatformOpt
return function (webpackConfig) { return function (webpackConfig) {
// disable js cache-loader // disable js cache-loader
const rawRules = webpackConfig.module.rules const rawRules = webpackConfig.module.rules
for (let i = rawRules.length - 1; i >= 0; i--) { for (let i = rawRules.length - 1; i >= 0; i--) {
const uses = rawRules[i].use const uses = rawRules[i].use
if (Array.isArray(uses)) { if (Array.isArray(uses)) {
if (uses.find(use => use.loader === 'babel-loader')) { if (uses.find(use => use.loader === 'babel-loader')) {
const index = uses.findIndex(use => use.loader === 'cache-loader') const index = uses.findIndex(use => use.loader === 'cache-loader')
uses.splice(index, 1) if (process.env.UNI_USING_CACHE) {
Object.assign(uses[index].options, api.genCacheConfig(
'babel-loader/' + process.env.UNI_PLATFORM,
getPartialIdentifier()
))
} else {
uses.splice(index, 1)
}
} }
} }
} }
...@@ -168,7 +178,7 @@ module.exports = function configureWebpack (platformOptions, manifestPlatformOpt ...@@ -168,7 +178,7 @@ module.exports = function configureWebpack (platformOptions, manifestPlatformOpt
let platformWebpackConfig = platformOptions.webpackConfig let platformWebpackConfig = platformOptions.webpackConfig
if (typeof platformWebpackConfig === 'function') { if (typeof platformWebpackConfig === 'function') {
platformWebpackConfig = platformWebpackConfig(webpackConfig) platformWebpackConfig = platformWebpackConfig(webpackConfig, api)
} }
// 移除 node_modules 目录,避免受路径上的 node_modules 影响 // 移除 node_modules 目录,避免受路径上的 node_modules 影响
webpackConfig.resolve.modules = webpackConfig.resolve.modules.filter(module => module !== webpackConfig.resolve.modules = webpackConfig.resolve.modules.filter(module => module !==
......
const fs = require('fs')
const path = require('path') const path = require('path')
const mkdirp = require('mkdirp')
// 初始化环境变量 // 初始化环境变量
const defaultInputDir = '../../../../src' const defaultInputDir = '../../../../src'
...@@ -26,6 +28,10 @@ process.env.UNI_CLI_CONTEXT = path.resolve(__dirname, '../../../../') ...@@ -26,6 +28,10 @@ process.env.UNI_CLI_CONTEXT = path.resolve(__dirname, '../../../../')
process.UNI_LIBRARIES = process.UNI_LIBRARIES || ['@dcloudio/uni-ui'] process.UNI_LIBRARIES = process.UNI_LIBRARIES || ['@dcloudio/uni-ui']
if (process.env.NODE_ENV === 'production') { // 发行模式,不启用 cache
process.env.UNI_USING_CACHE = false
}
const { const {
isSupportSubPackages, isSupportSubPackages,
runByHBuilderX, runByHBuilderX,
...@@ -115,6 +121,8 @@ if (process.env.UNI_PLATFORM === 'app-plus') { ...@@ -115,6 +121,8 @@ if (process.env.UNI_PLATFORM === 'app-plus') {
isNVueCompiler = false isNVueCompiler = false
} }
if (platformOptions.renderer === 'native') { if (platformOptions.renderer === 'native') {
// 纯原生目前不提供 cache
process.env.UNI_USING_CACHE = false
process.env.UNI_USING_NATIVE = true process.env.UNI_USING_NATIVE = true
process.env.UNI_USING_V8 = true process.env.UNI_USING_V8 = true
process.env.UNI_OUTPUT_TMP_DIR = '' process.env.UNI_OUTPUT_TMP_DIR = ''
...@@ -254,8 +262,25 @@ if (runByHBuilderX) { ...@@ -254,8 +262,25 @@ if (runByHBuilderX) {
} }
} }
console.log(`正在编译中...`) if (
process.env.UNI_USING_CACHE &&
process.env.UNI_PLATFORM !== 'h5' &&
!process.env.UNI_USING_V3 &&
!process.env.UNI_USING_NATIVE
) { // 使用 cache, 拷贝 cache 的 json
const cacheJsonDir = path.resolve(
process.env.UNI_CLI_CONTEXT,
'node_modules/.cache/uni-pages-loader/' + process.env.UNI_PLATFORM
)
if (!fs.existsSync(cacheJsonDir)) { // 创建 cache 目录
mkdirp(cacheJsonDir)
} else {
require('@dcloudio/uni-cli-shared/lib/cache').restore()
}
}
runByHBuilderX && console.log(`正在编译中...`)
module.exports = { module.exports = {
manifestPlatformOptions: platformOptions manifestPlatformOptions: platformOptions
} }
...@@ -4,10 +4,11 @@ const path = require('path') ...@@ -4,10 +4,11 @@ const path = require('path')
const { const {
getMainEntry, getMainEntry,
getH5Options, getH5Options,
getPlatformCompiler,
getPlatformCssnano getPlatformCssnano
} = require('@dcloudio/uni-cli-shared') } = require('@dcloudio/uni-cli-shared')
const modifyVueLoader = require('../vue-loader')
const WebpackHtmlAppendPlugin = require('../../packages/webpack-html-append-plugin') const WebpackHtmlAppendPlugin = require('../../packages/webpack-html-append-plugin')
function resolve (dir) { function resolve (dir) {
...@@ -100,7 +101,7 @@ module.exports = { ...@@ -100,7 +101,7 @@ module.exports = {
plugins plugins
} }
}, },
chainWebpack (webpackConfig) { chainWebpack (webpackConfig, api) {
webpackConfig.plugins.delete('copy') webpackConfig.plugins.delete('copy')
if (!process.env.UNI_OPT_PREFETCH) { if (!process.env.UNI_OPT_PREFETCH) {
...@@ -109,29 +110,8 @@ module.exports = { ...@@ -109,29 +110,8 @@ module.exports = {
if (!process.env.UNI_OPT_PRELOAD) { if (!process.env.UNI_OPT_PRELOAD) {
webpackConfig.plugins.delete('preload-index') webpackConfig.plugins.delete('preload-index')
} }
// Vue
webpackConfig.module modifyVueLoader(webpackConfig, require('./compiler-options'), api)
.rule('vue')
.test([/\.vue$/, /\.nvue$/])
.use('vue-loader')
.tap(options => Object.assign(options, {
compiler: getPlatformCompiler(),
compilerOptions: require('./compiler-options'),
cacheDirectory: false,
cacheIdentifier: false
}))
.end()
.use('uniapp-custom-block-loader')
.loader(require.resolve('@dcloudio/vue-cli-plugin-uni/packages/webpack-custom-block-loader'))
.options({
compiler: getPlatformCompiler()
})
.end()
.use('uniapp-scoped')
.loader(resolve('packages/webpack-scoped-loader'))
.end()
.uses
.delete('cache-loader')
if (process.env.NODE_ENV === 'production') { if (process.env.NODE_ENV === 'production') {
const module = webpackConfig.module const module = webpackConfig.module
......
...@@ -9,13 +9,14 @@ const { ...@@ -9,13 +9,14 @@ const {
parseEntry, parseEntry,
getMainEntry, getMainEntry,
getPlatformExts, getPlatformExts,
getPlatformCompiler,
getPlatformCssnano getPlatformCssnano
} = require('@dcloudio/uni-cli-shared') } = require('@dcloudio/uni-cli-shared')
const modifyVueLoader = require('./vue-loader')
const { const {
isUnaryTag createTemplateCacheLoader
} = require('./util') } = require('./cache-loader')
function createUniMPPlugin () { function createUniMPPlugin () {
if (process.env.UNI_USING_COMPONENTS) { if (process.env.UNI_USING_COMPONENTS) {
...@@ -42,7 +43,7 @@ function getProvides () { ...@@ -42,7 +43,7 @@ function getProvides () {
process.env.UNI_PLATFORM === 'app-plus' && process.env.UNI_PLATFORM === 'app-plus' &&
process.env.UNI_USING_V8 process.env.UNI_USING_V8
) { ) {
provides['__f__'] = [path.resolve(__dirname, 'format-log.js'), 'default'] provides['__f__'] = [path.resolve(__dirname, 'format-log.js'), 'default']
provides['crypto'] = [path.resolve(__dirname, 'crypto.js'), 'default'] provides['crypto'] = [path.resolve(__dirname, 'crypto.js'), 'default']
} }
...@@ -61,7 +62,7 @@ module.exports = { ...@@ -61,7 +62,7 @@ module.exports = {
vueConfig: { vueConfig: {
parallel: false parallel: false
}, },
webpackConfig (webpackConfig) { webpackConfig (webpackConfig, api) {
if (!webpackConfig.optimization) { if (!webpackConfig.optimization) {
webpackConfig.optimization = {} webpackConfig.optimization = {}
} }
...@@ -105,9 +106,9 @@ module.exports = { ...@@ -105,9 +106,9 @@ module.exports = {
chunkFilename: '[id].js', chunkFilename: '[id].js',
globalObject: process.env.UNI_PLATFORM === 'mp-alipay' ? 'my' : 'global', globalObject: process.env.UNI_PLATFORM === 'mp-alipay' ? 'my' : 'global',
sourceMapFilename: '../.sourcemap/' + process.env.UNI_PLATFORM + '/[name].js.map' sourceMapFilename: '../.sourcemap/' + process.env.UNI_PLATFORM + '/[name].js.map'
}, },
performance: { performance: {
hints: false hints: false
}, },
resolve: { resolve: {
extensions: ['.nvue'], extensions: ['.nvue'],
...@@ -132,7 +133,7 @@ module.exports = { ...@@ -132,7 +133,7 @@ module.exports = {
use: [{ use: [{
loader: '@dcloudio/webpack-uni-mp-loader/lib/template' loader: '@dcloudio/webpack-uni-mp-loader/lib/template'
}] }]
}, { }, createTemplateCacheLoader(api), {
resourceQuery: [ resourceQuery: [
/lang=wxs/, /lang=wxs/,
/lang=filter/, /lang=filter/,
...@@ -153,7 +154,7 @@ module.exports = { ...@@ -153,7 +154,7 @@ module.exports = {
] ]
} }
}, },
chainWebpack (webpackConfig) { chainWebpack (webpackConfig, api) {
if (process.env.UNI_PLATFORM === 'mp-baidu') { if (process.env.UNI_PLATFORM === 'mp-baidu') {
webpackConfig.module webpackConfig.module
.rule('js') .rule('js')
...@@ -161,32 +162,9 @@ module.exports = { ...@@ -161,32 +162,9 @@ module.exports = {
.add(/\.filter\.js$/) .add(/\.filter\.js$/)
} }
// disable vue cache-loader const compilerOptions = process.env.UNI_USING_COMPONENTS ? {} : require('./mp-compiler-options')
webpackConfig.module
.rule('vue') modifyVueLoader(webpackConfig, compilerOptions, api)
.test([/\.vue$/, /\.nvue$/])
.use('vue-loader')
.tap(options => Object.assign(options, {
compiler: getPlatformCompiler(),
compilerOptions: process.env.UNI_USING_COMPONENTS ? {
isUnaryTag,
preserveWhitespace: false
} : require('./mp-compiler-options'),
cacheDirectory: false,
cacheIdentifier: false
}))
.end()
.use('uniapp-custom-block-loader')
.loader(require.resolve('@dcloudio/vue-cli-plugin-uni/packages/webpack-custom-block-loader'))
.options({
compiler: getPlatformCompiler()
})
.end()
.use('uniapp-nvue-loader')
.loader(require.resolve('@dcloudio/webpack-uni-mp-loader/lib/style.js'))
.end()
.uses
.delete('cache-loader')
const styleExt = getPlatformExts().style const styleExt = getPlatformExts().style
......
...@@ -9,9 +9,24 @@ function makeMap (str, expectsLowerCase) { ...@@ -9,9 +9,24 @@ function makeMap (str, expectsLowerCase) {
: val => map[val] : val => map[val]
} }
let partialIdentifier = false
module.exports = { module.exports = {
isUnaryTag: makeMap( isUnaryTag: makeMap(
'image,area,base,br,col,embed,frame,hr,img,input,isindex,keygen,' + 'image,area,base,br,col,embed,frame,hr,img,input,isindex,keygen,' +
'link,meta,param,source,track,wbr' 'link,meta,param,source,track,wbr'
) ),
getPartialIdentifier () {
if (partialIdentifier) {
return partialIdentifier
}
partialIdentifier = {
'UNI_COMPILER_VERSION': require('../package.json').version
}
Object.keys(process.env).forEach(name => {
if (name.indexOf('UNI_') === 0) {
partialIdentifier[name] = process.env[name]
}
})
return partialIdentifier
}
} }
const {
getPlatformCompiler
} = require('@dcloudio/uni-cli-shared')
const {
isUnaryTag,
getPartialIdentifier
} = require('./util')
module.exports = function modifyVueLoader (webpackConfig, compilerOptions, api) {
// vue-loader options
const cacheConfig = {
cacheDirectory: false,
cacheIdentifier: false
}
const partialIdentifier = {}
if (process.env.UNI_USING_CACHE) {
Object.assign(cacheConfig, api.genCacheConfig(
'vue-template-compiler/' + process.env.UNI_PLATFORM,
getPartialIdentifier()
))
}
webpackConfig.module
.rule('vue')
.test([/\.vue$/, /\.nvue$/])
.use('vue-loader')
.tap(options => Object.assign(options, {
compiler: getPlatformCompiler(),
compilerOptions: Object.assign({
isUnaryTag,
preserveWhitespace: false
}, compilerOptions)
}, cacheConfig))
.end()
.use('uniapp-custom-block-loader')
.loader(require.resolve('@dcloudio/vue-cli-plugin-uni/packages/webpack-custom-block-loader'))
.options({
compiler: getPlatformCompiler()
})
// h5 框架需要使用 scoped 样式,其他平台编译时识别是否 nvue 文件且注入 flex 相关样式
if (process.env.UNI_PLATFORM === 'h5') {
webpackConfig.module
.rule('vue')
.use('uniapp-h5-style-scoped')
.loader(require.resolve('@dcloudio/vue-cli-plugin-uni/packages/webpack-scoped-loader'))
} else {
webpackConfig.module
.rule('vue')
.use('uniapp-nvue-style-loader')
.loader(require.resolve('@dcloudio/webpack-uni-mp-loader/lib/style.js'))
}
// 是否启用 cache
if (process.env.UNI_USING_CACHE) {
webpackConfig.module
.rule('vue')
.use('cache-loader')
.tap(options => Object.assign(options, api.genCacheConfig(
'vue-loader/' + process.env.UNI_PLATFORM,
partialIdentifier
)))
} else {
webpackConfig.module
.rule('vue')
.uses
.delete('cache-loader')
}
}
...@@ -18,11 +18,13 @@ ...@@ -18,11 +18,13 @@
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@dcloudio/uni-stat": "^2.0.0-23320190923002", "@dcloudio/uni-stat": "^2.0.0-23320190923002",
"buffer-json": "^2.0.0",
"copy-webpack-plugin": "^4.6.0", "copy-webpack-plugin": "^4.6.0",
"cross-env": "^5.2.0", "cross-env": "^5.2.0",
"envinfo": "^6.0.1", "envinfo": "^6.0.1",
"hash-sum": "^1.0.2", "hash-sum": "^1.0.2",
"loader-utils": "^1.1.0", "loader-utils": "^1.1.0",
"mkdirp": "^0.5.1",
"module-alias": "^2.1.0", "module-alias": "^2.1.0",
"postcss": "^7.0.7", "postcss": "^7.0.7",
"postcss-import": "^12.0.1", "postcss-import": "^12.0.1",
......
...@@ -5,8 +5,8 @@ const loaderUtils = require('loader-utils') ...@@ -5,8 +5,8 @@ const loaderUtils = require('loader-utils')
module.exports = function(content) { module.exports = function(content) {
this.cacheable && this.cacheable() this.cacheable && this.cacheable()
const vueLoaderOptions = this.loaders[0] const vueLoaderOptions = this.loaders.find(loader => loader.ident === 'vue-loader-options')
if (vueLoaderOptions.ident === 'vue-loader-options') { if (vueLoaderOptions) {
const params = loaderUtils.parseQuery(this.resourceQuery) const params = loaderUtils.parseQuery(this.resourceQuery)
/* eslint-disable no-mixed-operators */ /* eslint-disable no-mixed-operators */
const filterModules = JSON.parse(params && params['filter-modules'] || '{}') const filterModules = JSON.parse(params && params['filter-modules'] || '{}')
......
...@@ -82,7 +82,7 @@ function analyzeUsingComponents () { ...@@ -82,7 +82,7 @@ function analyzeUsingComponents () {
// pages[name] = usingComponentsMap[name] // pages[name] = usingComponentsMap[name]
// } // }
// return pages // return pages
// }, {}) // }, {})
} }
module.exports = function generateJson (compilation) { module.exports = function generateJson (compilation) {
...@@ -153,7 +153,7 @@ module.exports = function generateJson (compilation) { ...@@ -153,7 +153,7 @@ module.exports = function generateJson (compilation) {
!['app.js', 'manifest.js', 'project.config.js', 'project.swan.js'].includes(jsFile) && !['app.js', 'manifest.js', 'project.config.js', 'project.swan.js'].includes(jsFile) &&
!compilation.assets[jsFile] !compilation.assets[jsFile]
) { ) {
compilation.assets[jsFile] = { const jsFileAsset = {
size () { size () {
return Buffer.byteLength(EMPTY_COMPONENT, 'utf8') return Buffer.byteLength(EMPTY_COMPONENT, 'utf8')
}, },
...@@ -161,8 +161,9 @@ module.exports = function generateJson (compilation) { ...@@ -161,8 +161,9 @@ module.exports = function generateJson (compilation) {
return EMPTY_COMPONENT return EMPTY_COMPONENT
} }
} }
compilation.assets[jsFile] = jsFileAsset
} }
compilation.assets[name] = { const jsonAsset = {
size () { size () {
return Buffer.byteLength(source, 'utf8') return Buffer.byteLength(source, 'utf8')
}, },
...@@ -170,5 +171,12 @@ module.exports = function generateJson (compilation) { ...@@ -170,5 +171,12 @@ module.exports = function generateJson (compilation) {
return source return source
} }
} }
compilation.assets[name] = jsonAsset
}
if (process.env.UNI_USING_CACHE && jsonFileMap.size) {
setTimeout(() => {
require('@dcloudio/uni-cli-shared/lib/cache').store()
}, 50)
} }
} }
...@@ -32,8 +32,8 @@ const filterTagName = getPlatformFilterTag() || '' ...@@ -32,8 +32,8 @@ const filterTagName = getPlatformFilterTag() || ''
module.exports = function (content) { module.exports = function (content) {
this.cacheable && this.cacheable() this.cacheable && this.cacheable()
const vueLoaderOptions = this.loaders[0] const vueLoaderOptions = this.loaders.find(loader => loader.ident === 'vue-loader-options')
if (vueLoaderOptions.ident === 'vue-loader-options') { if (vueLoaderOptions) {
const globalUsingComponents = getGlobalUsingComponents() const globalUsingComponents = getGlobalUsingComponents()
const realResourcePath = path.relative(process.env.UNI_INPUT_DIR, this.resourcePath) const realResourcePath = path.relative(process.env.UNI_INPUT_DIR, this.resourcePath)
const resourcePath = normalizeNodeModules(removeExt(realResourcePath) + templateExt) const resourcePath = normalizeNodeModules(removeExt(realResourcePath) + templateExt)
......
...@@ -25,8 +25,8 @@ module.exports = function (content) { ...@@ -25,8 +25,8 @@ module.exports = function (content) {
if (process.env.UNI_USING_COMPONENTS) { if (process.env.UNI_USING_COMPONENTS) {
// 向 uni-template-compier 传递 emitFile // 向 uni-template-compier 传递 emitFile
const vueLoaderOptions = this.loaders[0] const vueLoaderOptions = this.loaders.find(loader => loader.ident === 'vue-loader-options')
if (vueLoaderOptions.ident === 'vue-loader-options') { if (vueLoaderOptions) {
Object.assign(vueLoaderOptions.options.compilerOptions, { Object.assign(vueLoaderOptions.options.compilerOptions, {
resourcePath: removeExt(realResourcePath) + templateExt, resourcePath: removeExt(realResourcePath) + templateExt,
emitFile: this.emitFile emitFile: this.emitFile
...@@ -57,8 +57,8 @@ module.exports = function (content) { ...@@ -57,8 +57,8 @@ module.exports = function (content) {
cacheCompilerOptions(realResourcePath, compilerOptions) cacheCompilerOptions(realResourcePath, compilerOptions)
// 向 vue-loader templateLoader 传递 compilerOptions // 向 vue-loader templateLoader 传递 compilerOptions
const vueLoaderOptions = this.loaders[0] const vueLoaderOptions = this.loaders.find(loader => loader.ident === 'vue-loader-options')
if (vueLoaderOptions.ident === 'vue-loader-options') { if (vueLoaderOptions) {
Object.assign(vueLoaderOptions.options.compilerOptions, compilerOptions) Object.assign(vueLoaderOptions.options.compilerOptions, compilerOptions)
} else { } else {
throw new Error('vue-loader-options parse error') throw new Error('vue-loader-options parse error')
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册