Skip to content

Commit

Permalink
⚙️ webpack: improve bundle build
Browse files Browse the repository at this point in the history
Fixes #52.

Signed-off-by: Dennis Reimann <mail@dennisreimann.de>

bla

Signed-off-by: Dennis Reimann <mail@dennisreimann.de>
  • Loading branch information
dennisreimann committed Aug 20, 2019
1 parent 7b2cd98 commit 6b5d570
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 68 deletions.
4 changes: 2 additions & 2 deletions packages/adapter-webpack/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
"dependencies": {
"@uiengine/util": "2.3.1",
"globby": "10.0.1",
"htmlescape": "1.1.1",
"object-hash": "^1.3.1",
"require-from-string": "2.0.2"
},
Expand All @@ -49,7 +48,8 @@
"vue-template-compiler": "2.6.10",
"webpack": "4.39.2",
"webpack-merge": "4.2.1",
"webpack-node-externals": "1.7.2"
"webpack-node-externals": "1.7.2",
"webpack-virtual-modules": "^0.1.11"
},
"optionalDependencies": {
"parse-prop-types": "0.3.0",
Expand Down
9 changes: 5 additions & 4 deletions packages/adapter-webpack/src/deps.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,13 @@ async function getDependencyFiles (options, filePath, cache) {
// cache the promises so that files do not get added multiple times
const promise = new Promise((resolve, reject) => {
buildQueued(options, filePath)
.then(({ serverChunk, clientChunk }) => {
const chunk = serverChunk || clientChunk
.then(({ serverComponentChunk, clientComponentChunk }) => {
const chunk = serverComponentChunk || clientComponentChunk

// https://webpack.js.org/api/stats#chunk-objects
const filePaths = chunk ? chunk.modules.map(({ id }) => {
const mod = id.split('?!').pop().replace(/\?.*$/, '')
const filePaths = chunk ? chunk.modules.map(({ id, name }) => {
const ident = typeof id === 'number' ? (name.match(/\s([^\s]*)/g) || ['']).shift().trim() : id
const mod = ident && ident.split('?!').pop().replace(/\?.*$/, '')
let modulePath
if (mod) modulePath = mod.startsWith('.') ? path.resolve(mod) : require.resolve(mod)
return modulePath && crossPlatformPath(modulePath)
Expand Down
32 changes: 8 additions & 24 deletions packages/adapter-webpack/src/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@

const htmlescape = require('htmlescape')
const { FileUtil: { requireUncached } } = require('@uiengine/util')
const { extractDependentFiles, extractDependencyFiles } = require('./deps')
const { buildSetup, buildQueued, getExtractProperties } = require('./util')

Expand All @@ -18,7 +17,7 @@ async function setup (options) {
}

async function registerComponentFile (options, filePath) {
await buildQueued(options, filePath, true)
await buildQueued(options, filePath, undefined, true)

const extractProperties = getExtractProperties(options)
const [properties, dependentFiles, dependencyFiles] = await Promise.all([
Expand All @@ -37,32 +36,17 @@ async function registerComponentFile (options, filePath) {

async function render (options, filePath, data = {}) {
let rendered, foot
const { serverRenderPath, serverComponentPath, clientRenderPath, clientComponentPath } = await buildQueued(options, filePath, true)
const { serverResultPath, clientResultPath } = await buildQueued(options, filePath, data, true)

if (serverRenderPath && serverComponentPath) {
const ServerRender = require(serverRenderPath)
const ServerComponent = require(serverComponentPath)
const serverRender = ServerRender.default || ServerRender
const serverComponent = ServerComponent.default || ServerComponent
rendered = await serverRender(serverComponent, data)
if (serverResultPath) {
rendered = await requireUncached(serverResultPath)
}

if (clientRenderPath && clientComponentPath) {
foot = `
<script src="${clientRenderPath}"></script>
<script src="${clientComponentPath}"></script>
<script>
window.UIengineWebpack_render(
window.UIengineWebpack_component,
${htmlescape(data)}
)
</script>`
if (clientResultPath) {
foot = ` <script src="${clientResultPath}"></script>`
}

return {
rendered,
foot
}
return { rendered, foot }
}

function filesForComponent (options, componentName) {
Expand Down
100 changes: 67 additions & 33 deletions packages/adapter-webpack/src/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const { join, relative } = require('path')
const hash = require('object-hash')
const webpack = require('webpack')
const merge = require('webpack-merge')
const VirtualModulesPlugin = require('webpack-virtual-modules')
const { DebounceUtil: { debounce } } = require('@uiengine/util')
const { cacheGet, cachePut, cacheDel } = require('./cache')

Expand Down Expand Up @@ -56,9 +57,6 @@ const buildConfig = (options, isSetupBuild = false) => {
const entry = isSetupBuild
? { [`${ext}-client`]: clientRenderPath }
: {}
const library = isSetupBuild
? 'UIengineWebpack_render'
: 'UIengineWebpack_component'

config.client = merge(clientConfig, {
name: WEBPACK_NAME_CLIENT,
Expand All @@ -67,10 +65,7 @@ const buildConfig = (options, isSetupBuild = false) => {
entry,
output: {
path: filesDir(options),
filename: '[name].js',
library,
libraryTarget: 'window',
libraryExport: 'default'
filename: '[name].js'
},
plugins: [
new webpack.DefinePlugin({
Expand All @@ -83,24 +78,63 @@ const buildConfig = (options, isSetupBuild = false) => {
return config
}

const addFileToQueue = (options, filePath, queue) => {
const addFileToQueue = (options, filePath, data, queue) => {
if (queue.promises[filePath]) return queue.promises[filePath]

const { serverConfig, clientConfig } = options
const serverId = getFileId(filePath, 'server')
const clientId = getFileId(filePath, 'client')
const { serverConfig, serverRenderPath, clientConfig, clientRenderPath } = options
const serverComponentId = getFileId(filePath, 'server-component')
const serverResultId = getFileId(filePath, 'server-result')
const clientComponentId = getFileId(filePath, 'client-component')
const clientResultId = getFileId(filePath, 'client-result')

if (serverConfig) {
queue.config.server.entry[serverComponentId] = filePath

if (data) {
queue.config.server.entry[serverResultId] = `/${serverResultId}.js`
queue.config.server.plugins.push(
new VirtualModulesPlugin({
[queue.config.server.entry[serverResultId]]: `
const ServerRender = require('${serverRenderPath}')
const ServerComponent = require('${filePath}')
const serverRender = ServerRender.default || ServerRender
const serverComponent = ServerComponent.default || ServerComponent
module.exports = serverRender(serverComponent, ${JSON.stringify(data)})
`
})
)
}
}

if (clientConfig) {
queue.config.client.entry[clientComponentId] = filePath

if (serverConfig) queue.config.server.entry[serverId] = filePath
if (clientConfig) queue.config.client.entry[clientId] = filePath
if (data) {
queue.config.client.entry[clientResultId] = `/${clientResultId}.js`
queue.config.client.plugins.push(
new VirtualModulesPlugin({
[queue.config.client.entry[clientResultId]]: `
import clientRender from '${clientRenderPath}'
import Component from '${filePath}'
export default clientRender(Component, ${JSON.stringify(data)})
`
})
)
}
}

// cache the promises so that files do not get added multiple times
const promise = new Promise((resolve, reject) => {
queue.handles[filePath] = {
reject,
resolve,
filePath,
serverId,
clientId
serverComponentId,
serverResultId,
clientComponentId,
clientResultId
}
})

Expand Down Expand Up @@ -149,7 +183,7 @@ async function buildSetup (options) {
await runWebpack(config)
}

async function buildQueued (options, filePath, clearCache = false) {
async function buildQueued (options, filePath, data = {}, clearCache = false) {
const queueId = getQueueId(options)

if (clearCache) {
Expand All @@ -167,7 +201,7 @@ async function buildQueued (options, filePath, clearCache = false) {
}
}

const promise = addFileToQueue(options, filePath, QUEUES[queueId])
const promise = addFileToQueue(options, filePath, data, QUEUES[queueId])

debounce(queueId, async () => {
const { config, handles } = QUEUES[queueId]
Expand All @@ -178,25 +212,25 @@ async function buildQueued (options, filePath, clearCache = false) {
const info = stats.toJson()
const serverInfo = info.children.find(child => child.name === WEBPACK_NAME_SERVER)
const clientInfo = info.children.find(child => child.name === WEBPACK_NAME_CLIENT)
const { ext, uiBase } = options

Object.values(handles).forEach(({ resolve, filePath, serverId, clientId }) => {
const serverChunk = serverInfo && serverInfo.chunks.find(chunk => chunk.id === serverId)
const clientChunk = clientInfo && clientInfo.chunks.find(chunk => chunk.id === clientId)
const serverRenderPath = serverChunk && join(filesDir(options), `${ext}-server.js`)
const serverComponentPath = serverChunk && join(filesDir(options), `${getFileId(filePath, 'server')}.js`)
const clientRenderPath = clientChunk && `${uiBase}${TARGET_FOLDER}/${ext}-client.js`
const clientComponentPath = clientChunk && `${uiBase}${TARGET_FOLDER}/${getFileId(filePath, 'client')}.js`
const { uiBase } = options

Object.values(handles).forEach(({ resolve, filePath, serverComponentId, clientComponentId }) => {
// needed for dependency resolution
const serverComponentChunk = serverInfo && serverInfo.chunks.find(chunk => chunk.id === serverComponentId)
const clientComponentChunk = clientInfo && clientInfo.chunks.find(chunk => chunk.id === clientComponentId)
// needed for property extraction
const serverComponentPath = serverComponentChunk && join(filesDir(options), `${getFileId(filePath, 'server-component')}.js`)
// needed for rendering
const serverResultPath = serverComponentChunk && join(filesDir(options), `${getFileId(filePath, 'server-result')}.js`)
const clientResultPath = clientComponentChunk && `${uiBase}${TARGET_FOLDER}/${getFileId(filePath, 'client-result')}.js`

// console.log(serverId, serverChunk, serverInfo.chunks)
const object = {
filePath,
serverChunk,
serverRenderPath,
serverComponentPath,
clientChunk,
clientRenderPath,
clientComponentPath
clientComponentChunk,
clientResultPath,
serverComponentChunk,
serverResultPath,
serverComponentPath
}

cachePut(queueId, filePath, object)
Expand Down
4 changes: 2 additions & 2 deletions packages/adapter-webpack/test/webpack_adapter_react_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const assert = require('assert')
const { join } = require('path')
const { removeSync } = require('fs-extra')
const { StringUtil: { crossPlatformPath } } = require('@uiengine/util')
const { assertMatches, assertIncludes, assertContentMatches } = require('../../../test/support/asserts')
const { assertMatches, assertIncludes, assertExists } = require('../../../test/support/asserts')
const { testTmpPath } = require('../../../test/support/paths')

const Adapter = require('../src/index')
Expand Down Expand Up @@ -67,7 +67,7 @@ describe('Webpack adapter with React templates', function () {
await Adapter.setup(options)

const clientPath = join(outputPath, 'jsx-client.js')
assertContentMatches(clientPath, 'window["UIengineWebpack_render"]')
assertExists(clientPath)

const serverPath = join(outputPath, 'jsx-server.js')
const serverRender = require(serverPath)
Expand Down
4 changes: 2 additions & 2 deletions packages/adapter-webpack/test/webpack_adapter_vue_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const assert = require('assert')
const { join } = require('path')
const { removeSync } = require('fs-extra')
const { StringUtil: { crossPlatformPath } } = require('@uiengine/util')
const { assertMatches, assertIncludes, assertContentMatches } = require('../../../test/support/asserts')
const { assertMatches, assertIncludes, assertExists } = require('../../../test/support/asserts')
const { testTmpPath } = require('../../../test/support/paths')

const Adapter = require('../src/index')
Expand Down Expand Up @@ -67,7 +67,7 @@ describe('Webpack adapter with Vue templates', function () {
await Adapter.setup(options)

const clientPath = join(outputPath, 'vue-client.js')
assertContentMatches(clientPath, 'window["UIengineWebpack_render"]')
assertExists(clientPath)

const serverPath = join(outputPath, 'vue-server.js')
const serverRender = require(serverPath)
Expand Down
9 changes: 8 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4786,7 +4786,7 @@ debug@3.1.0, debug@=3.1.0, debug@~3.1.0:
dependencies:
ms "2.0.0"

debug@3.2.6, debug@^3.1.0, debug@^3.2.6:
debug@3.2.6, debug@^3.0.0, debug@^3.1.0, debug@^3.2.6:
version "3.2.6"
resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b"
integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==
Expand Down Expand Up @@ -14491,6 +14491,13 @@ webpack-sources@^1.4.0, webpack-sources@^1.4.1:
source-list-map "^2.0.0"
source-map "~0.6.1"

webpack-virtual-modules@^0.1.11:
version "0.1.11"
resolved "https://registry.yarnpkg.com/webpack-virtual-modules/-/webpack-virtual-modules-0.1.11.tgz#8f82c74c0cc8d1ea05a0d5ed40fbe2b9b00a3ef5"
integrity sha512-cyaaKMkICVP333iPx+74f3azZ18qKWyvViLn0FnaU9xFki+jtdOfPlkxjQVKnSbE+0Hxz7GUEuDTU+boikWTvQ==
dependencies:
debug "^3.0.0"

webpack@4.39.2:
version "4.39.2"
resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.39.2.tgz#c9aa5c1776d7c309d1b3911764f0288c8c2816aa"
Expand Down

0 comments on commit 6b5d570

Please sign in to comment.