Skip to content

Commit

Permalink
Merge pull request #22 from kaola-fed/issue12
Browse files Browse the repository at this point in the history
feat: support use .vue file as entry, closes #12
  • Loading branch information
fengzilong authored Dec 3, 2018
2 parents 757cfb0 + 635f8d2 commit 03ef02b
Show file tree
Hide file tree
Showing 13 changed files with 170 additions and 18 deletions.
6 changes: 0 additions & 6 deletions examples/vue-mp/src/pages/counter/index.js

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,9 @@ export default {
font-size: 29px;
}
</style>

<config>
{
"a": 1
}
</config>
2 changes: 1 addition & 1 deletion examples/vue-mp/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ module.exports = {
entry: {
'app': path.resolve( __dirname, 'src/index.js' ),
'package/pages/demo/index': path.resolve( __dirname, 'src/package/pages/demo/index.js' ),
'pages/counter/index': path.resolve( __dirname, 'src/pages/counter/index.js' ),
'pages/counter/index': path.resolve( __dirname, 'src/pages/counter/index.vue' ),
'pages/todomvc/index': path.resolve( __dirname, 'src/pages/todomvc/index.js' ),
},

Expand Down
30 changes: 29 additions & 1 deletion packages/target/lib/frameworks/shared/plugin/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,22 @@ class FrameworkPlugin {
frameworkLoaderRegexp,
compiler: templateCompiler,
entryLoader,
pitcherLoader
pitcherLoader,
} = this.options || {}

// .[framework] maybe used as entry
if ( entryLoader ) {
hookFrameworkEntry( {
rules,
files: sfcFiles,
frameworkLoaderRegexp,
entryLoader: {
options: {},
loader: entryLoader,
},
} )
}

// generate components
replaceTemplateCompiler( {
rules,
Expand All @@ -40,6 +53,21 @@ class FrameworkPlugin {
}
}

function hookFrameworkEntry( { rules, files = {}, frameworkLoaderRegexp, entryLoader } ) {
const entryRule = findRuleByFile( rules, files )

if ( !entryRule ) {
return
}

const entryUse = entryRule.use
const vueUseLoaderIndex = entryUse.findIndex( u => {
return frameworkLoaderRegexp.test( u.loader )
} )

entryUse.splice( vueUseLoaderIndex, 0, entryLoader )
}

// add our loader before [framework]-loader
function replaceTemplateCompiler( { rules, compiler, files = [], frameworkLoaderRegexp } ) {
const rule = findRuleByFile( rules, files )
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
const { babel } = require( '../../../utils/babel' )
const extractConfigPlugin = require( '../../../babel-plugins/extract-config' )
const entryComponentPlugin = require( '../../../babel-plugins/entry-component' )
const mpTypePlugin = require( '../../../babel-plugins/mptype' )
const resolveSource = require( '../../../utils/resolveSource' )
const hashify = require( '../../../utils/hashify' )
const removeExtension = require( '../../../utils/removeExtension' )

module.exports = function ( source, loaderContext ) {
const entryHelper = loaderContext.megaloEntryHelper

const resourcePath = removeExtension( loaderContext.resourcePath, '.js' )

if ( entryHelper.isEntry( resourcePath ) ) {
const entryKey = entryHelper.getEntryKey( resourcePath )

return Promise.resolve( {
file: entryKey,
config: null,
entryComponent: {
name: hashify( resourcePath ),
},
} )
}

return Promise.resolve( null )
}
28 changes: 28 additions & 0 deletions packages/target/lib/frameworks/vue/loader/config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
const toString = Object.prototype.toString

module.exports = function ( source ) {
const loaderContext = this

const entryHelper = loaderContext.megaloEntryHelper

if ( entryHelper.isEntry( loaderContext.resourcePath ) ) {
const entryKey = entryHelper.getEntryKey( loaderContext.resourcePath )

let config
try {
config = JSON.parse( source )
if ( toString.call( config ) !== '[object Object]' ) {
config = {}
}
} catch ( e ) {
config = {}
}

loaderContext.megaloCacheToPages( {
file: entryKey,
config: config,
} )
}

return ''
}
17 changes: 17 additions & 0 deletions packages/target/lib/frameworks/vue/loader/pitcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ const qs = require( 'querystring' )
const loaderUtils = require( 'loader-utils' )
const hash = require( 'hash-sum' )
const selfPath = require.resolve( 'vue-loader' )
const vueEntryPath = require.resolve( './vue-entry' )
const styleLoaderPath = require.resolve( './style' )
const templateLoaderPath = require.resolve( './template' )
const scriptLoaderPath = require.resolve( './script' )
const configLoaderPath = require.resolve( './config' )

const isESLintLoader = l => /(\/|\\|@)eslint-loader/.test(l.path)
const isNullLoader = l => /(\/|\\|@)null-loader/.test(l.path)
Expand Down Expand Up @@ -53,6 +55,8 @@ module.exports.pitch = function (remainingRequest) {

// remove self
loaders = loaders.filter(isPitcher)
// remove vue entry loader
loaders = loaders.filter( l => l.path !== vueEntryPath )

// do not inject if user uses null-loader to void the type (#1239)
if (loaders.some(isNullLoader)) {
Expand Down Expand Up @@ -140,6 +144,19 @@ module.exports.pitch = function (remainingRequest) {
}
}

// handle config block
if (
query.type === 'custom' &&
query.blockType === 'config'
) {
const vueLoader = loaders.find( l => l.path = selfPath )
const request = genRequest( [
configLoaderPath,
].concat( vueLoader ? [ vueLoader ] : [] ) )

return `import mod from ${request}; export default mod; export * from ${request}`
}

// if a custom block has no other matching loader other than vue-loader itself,
// we should ignore it
if (query.type === `custom` &&
Expand Down
19 changes: 16 additions & 3 deletions packages/target/lib/frameworks/vue/loader/script.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,33 @@
const path = require( 'path' )
const extractCompilerOptionsFromScriptSource =
require( '../../shared/utils/extractCompilerOptionsFromScriptSource' )
const extractPageFromScriptSource =
require( '../../shared/utils/extractPageFromScriptSource' )
const removeExtension = require( '../../../utils/removeExtension' )

module.exports = function ( source ) {
const loaderContext = this
const callback = loaderContext.async()
const realResourcePath = removeExtension( loaderContext.resourcePath, '.js' )

let realResourcePath = removeExtension( loaderContext.resourcePath )
const jobs = [
extractCompilerOptionsFromScriptSource( source, loaderContext ),
extractPageFromScriptSource( source, loaderContext ),
]

Promise.all( jobs )
.then( data => {
const [ compilerOptions, page ] = data || []

extractCompilerOptionsFromScriptSource( source, loaderContext )
.then( compilerOptions => {
loaderContext.megaloCacheToAllCompilerOptions(
realResourcePath,
compilerOptions,
)

if ( page ) {
loaderContext.megaloCacheToPages( page )
}

callback( null, source )
} )
.catch( e => {
Expand Down
25 changes: 25 additions & 0 deletions packages/target/lib/frameworks/vue/loader/vue-entry.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
const qs = require( 'querystring' )

module.exports = source => source

module.exports.pitch = function ( remainingRequest ) {
const loaderContext = this
const query = qs.parse( loaderContext.resourceQuery.slice( 1 ) )
const entryHelper = loaderContext.megaloEntryHelper

// handle *.[framework] as entry
if ( entryHelper.isEntry( loaderContext.resourcePath ) ) {
const entryKey = entryHelper.getEntryKey( loaderContext.resourcePath )

// only pitch in first time
if ( typeof query.vue === 'undefined' ) {
return `
import Component from ${ JSON.stringify( '-!' + remainingRequest ) };
import Vue from 'vue';
Component.mpType = "${ entryKey === 'app' ? 'app' : 'page' }";
const app = new Vue(Component);
app.$mount();
`
}
}
}
1 change: 1 addition & 0 deletions packages/target/lib/frameworks/vue/plugin/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class VuePlugin {
frameworkLoaderRegexp: /^vue-loader|(\/|\\|@)vue-loader/,
pitcherLoader: require.resolve( '../loader/pitcher' ),
compiler: options.compiler.vue,
entryLoader: require.resolve( '../loader/vue-entry' )
} )
).apply( compiler )
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
const path = require( 'path' )
const semver = require( 'semver' )
const { babel } = require( '../utils/babel' )
const extractConfigPlugin = require( '../babel-plugins/extract-config' )
const entryComponentPlugin = require( '../babel-plugins/entry-component' )
Expand Down
3 changes: 1 addition & 2 deletions packages/target/lib/platforms/wechat/codegen/page.json.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
const composePlatformConfig = require( '../../shared/utils/composePlatformConfig' )

module.exports = function ( { config } ) {
module.exports = function ( { config = {} } ) {
const _config = composePlatformConfig( config, 'wechat' )
return JSON.stringify( _config, 0, 2 )
}

23 changes: 19 additions & 4 deletions packages/target/lib/plugins/MegaloPlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,12 @@ class MegaloPlugin {
replaceGlobalObject( compiler, megaloOptions )

// generate pages
hookEntry( {
hookJSEntry( {
rules,
files: [ 'foo.js', 'foo.ts' ],
entryLoader: {
options: {},
loader: require.resolve( '../loaders/entry' ),
loader: require.resolve( '../loaders/js-entry' ),
},
} )

Expand All @@ -59,7 +59,7 @@ function replaceGlobalObject( compiler, megaloOptions ) {
}

// [framework]-loader clones babel-loader rule, we shall ignore it
function hookEntry( { rules, files = {}, entryLoader } ) {
function hookJSEntry( { rules, files = {}, entryLoader } ) {
const entryRule = findRuleByFile( rules, files )

if ( !entryRule ) {
Expand Down Expand Up @@ -196,7 +196,22 @@ function attachCacheAPI( compiler ) {

// sideEffects: true
function cacheToPages( { file, config, entryComponent } = {} ) {
pages[ file ] = { file, config, entryComponent }
if ( !pages[ file ] ) {
pages[ file ] = {}
}

if ( file ) {
pages[ file ].file = file
}

// merge config
if ( config ) {
pages[ file ].config = Object.assign( {}, pages[ file ].config || {}, config )
}

if ( entryComponent ) {
pages[ file ].entryComponent = entryComponent
}
}

function cacheToAllCompilerOptions( resourcePath, compilerOptions = {} ) {
Expand Down

0 comments on commit 03ef02b

Please sign in to comment.