glass-easel-miniprogram-webpack-plugin 0.7.0 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +86 -0
- package/index.js +68 -16
- package/index.ts +99 -21
- package/package.json +6 -5
- package/wxss_loader.js +17 -3
package/README.md
CHANGED
|
@@ -8,6 +8,47 @@ Refer to the [glass-easel](https://github.com/wechat-miniprogram/glass-easel) pr
|
|
|
8
8
|
|
|
9
9
|
See the [template](../glass-easel-miniprogram-template/).
|
|
10
10
|
|
|
11
|
+
The `GlassEaselMiniprogramWxmlLoader` loader must be added to handle `.wxml` files, and the `GlassEaselMiniprogramWxssLoader` loader must be added to handle `.wxss` files. They can work with other loaders.
|
|
12
|
+
|
|
13
|
+
```js
|
|
14
|
+
{
|
|
15
|
+
test: /\.wxml$/,
|
|
16
|
+
use: GlassEaselMiniprogramWxmlLoader,
|
|
17
|
+
exclude: /node_modules/,
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
test: /\.wxss$/,
|
|
21
|
+
use: [
|
|
22
|
+
'css-loader',
|
|
23
|
+
GlassEaselMiniprogramWxssLoader,
|
|
24
|
+
],
|
|
25
|
+
exclude: /node_modules/,
|
|
26
|
+
},
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Furthurmore, a webpack plugin that compiles a mini-program-like directory structure should be added. The directory should be specified in the plugin options.
|
|
30
|
+
|
|
31
|
+
```js
|
|
32
|
+
plugins: [
|
|
33
|
+
new GlassEaselMiniprogramWebpackPlugin({
|
|
34
|
+
path: path.join(__dirname, 'src'),
|
|
35
|
+
resourceFilePattern: /\.(jpg|jpeg|png|gif|html)$/,
|
|
36
|
+
defaultEntry: 'pages/index/index',
|
|
37
|
+
}),
|
|
38
|
+
],
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
| Options | Explanation |
|
|
42
|
+
| ------- | ----------- |
|
|
43
|
+
| dev | compile with more debug information (default to `false` if the webpack is in `production` mode) |
|
|
44
|
+
| path | the mini-program-like directory to be compiled (default to `src` ) |
|
|
45
|
+
| resourceFilePattern | the filename pattern (in the mini-program-like directory) to be copied into the webpack output path |
|
|
46
|
+
| defaultEntry | the mini-program page to be loaded on startup |
|
|
47
|
+
| customBootstrap | (see the *Custom Bootstrap* section below) |
|
|
48
|
+
| disableClassPrefix | (see the *Custom Bootstrap* section below) |
|
|
49
|
+
|
|
50
|
+
The plugin will generate a virtual `index.js` file in the mini-program-like directory (a.k.a. `src/index.js` by default). This file can be used as the webpack entry or be imported by other modules.
|
|
51
|
+
|
|
11
52
|
## Custom Bootstrap
|
|
12
53
|
|
|
13
54
|
By default, the plugin inserts a bootstrap code to insert the `defaultEntry` into DOM `<body>` 。
|
|
@@ -21,3 +62,48 @@ new GlassEaselMiniprogramWebpackPlugin({
|
|
|
21
62
|
```
|
|
22
63
|
|
|
23
64
|
Furthermore, if the backend handles stylesheets unlike DOM, another `disableClassPrefix` may be required to be `true` depending on the backend.
|
|
65
|
+
|
|
66
|
+
When using custom bootstrap, the plugin will generate a module which has the following types:
|
|
67
|
+
|
|
68
|
+
```ts
|
|
69
|
+
import type * as adapter from 'glass-easel-miniprogram-adapter'
|
|
70
|
+
|
|
71
|
+
export declare const env: adapter.MiniProgramEnv
|
|
72
|
+
export declare const codeSpace: adapter.CodeSpace
|
|
73
|
+
export declare const registerGlobalEventListener: (
|
|
74
|
+
backend: adapter.glassEasel.GeneralBackendContext,
|
|
75
|
+
) => void
|
|
76
|
+
export declare const initWithBackend: (
|
|
77
|
+
backend: adapter.glassEasel.GeneralBackendContext,
|
|
78
|
+
) => adapter.AssociatedBackend
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
You can put the code above into a `d.ts` file ( `src.d.ts` by default).
|
|
82
|
+
|
|
83
|
+
A page can be loaded like this:
|
|
84
|
+
|
|
85
|
+
```js
|
|
86
|
+
import * as glassEasel from 'glass-easel'
|
|
87
|
+
import { codeSpace, initWithBackend, registerGlobalEventListener } from './src' // import the plugin-generated code
|
|
88
|
+
|
|
89
|
+
// create the backend context
|
|
90
|
+
const backendContext = new glassEasel.CurrentWindowBackendContext() // or another backend context
|
|
91
|
+
registerGlobalEventListener(backendContext)
|
|
92
|
+
const ab = initWithBackend(backendContext)
|
|
93
|
+
|
|
94
|
+
// create a mini-program page
|
|
95
|
+
const root = ab.createRoot(
|
|
96
|
+
'glass-easel-root', // the tag name of the mount point
|
|
97
|
+
codeSpace,
|
|
98
|
+
'pages/index/index', // the mini-program page to load
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
// insert the page into backend
|
|
102
|
+
// (this step is backend-related - if the backend is not DOM, refer to the backend documentation)
|
|
103
|
+
const placeholder = document.createElement('span')
|
|
104
|
+
document.body.appendChild(placeholder)
|
|
105
|
+
root.attach(
|
|
106
|
+
document.body as unknown as glassEasel.GeneralBackendElement,
|
|
107
|
+
placeholder as unknown as glassEasel.GeneralBackendElement,
|
|
108
|
+
)
|
|
109
|
+
```
|
package/index.js
CHANGED
|
@@ -32,11 +32,15 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
32
32
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
33
33
|
});
|
|
34
34
|
};
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
35
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
39
|
exports.GlassEaselMiniprogramWebpackPlugin = exports.GlassEaselMiniprogramWxssLoader = exports.GlassEaselMiniprogramWxmlLoader = void 0;
|
|
37
40
|
const node_fs_1 = require("node:fs");
|
|
38
41
|
const path = __importStar(require("node:path"));
|
|
39
42
|
const webpack_1 = require("webpack");
|
|
43
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
40
44
|
const glass_easel_template_compiler_1 = require("glass-easel-template-compiler");
|
|
41
45
|
const helpers_1 = require("./helpers");
|
|
42
46
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
@@ -49,6 +53,7 @@ exports.GlassEaselMiniprogramWxmlLoader = path.join(__dirname, 'wxml_loader.js')
|
|
|
49
53
|
exports.GlassEaselMiniprogramWxssLoader = path.join(__dirname, 'wxss_loader.js');
|
|
50
54
|
const PLUGIN_NAME = 'GlassEaselMiniprogramWebpackPlugin';
|
|
51
55
|
const CACHE_ETAG = 1;
|
|
56
|
+
const HOST_STYLES_MODULE = '__glass_easel_host_styles__.wxss';
|
|
52
57
|
const readCache = (compiler, key) => new Promise((resolve) => {
|
|
53
58
|
const cacheKey = `${PLUGIN_NAME}|${key}`;
|
|
54
59
|
compiler.cache.get(cacheKey, CACHE_ETAG, (err, cache) => {
|
|
@@ -67,11 +72,14 @@ const writeCache = (compiler, key, value) => new Promise((resolve) => {
|
|
|
67
72
|
});
|
|
68
73
|
});
|
|
69
74
|
class StyleSheetManager {
|
|
70
|
-
constructor(disableClassPrefix) {
|
|
75
|
+
constructor(disableClassPrefix, codeRoot, virtualModules) {
|
|
71
76
|
this.map = Object.create(null);
|
|
72
77
|
this.enableStyleScope = Object.create(null);
|
|
73
78
|
this.scopeNameInc = 0;
|
|
79
|
+
this.hostStylesReady = false;
|
|
74
80
|
this.disableClassPrefix = disableClassPrefix;
|
|
81
|
+
this.codeRoot = codeRoot;
|
|
82
|
+
this.virtualModules = virtualModules;
|
|
75
83
|
}
|
|
76
84
|
add(compPath, srcPath) {
|
|
77
85
|
let scopeNameNum = this.scopeNameInc;
|
|
@@ -92,6 +100,7 @@ class StyleSheetManager {
|
|
|
92
100
|
this.map[compPath] = {
|
|
93
101
|
srcPath,
|
|
94
102
|
scopeName,
|
|
103
|
+
lowPriority: '',
|
|
95
104
|
};
|
|
96
105
|
}
|
|
97
106
|
setStyleIsolation(compPath, styleIsolation, isComponent) {
|
|
@@ -109,14 +118,29 @@ class StyleSheetManager {
|
|
|
109
118
|
}
|
|
110
119
|
return undefined;
|
|
111
120
|
}
|
|
121
|
+
setLowPriorityStyles(compPath, source, _map) {
|
|
122
|
+
const meta = this.map[compPath];
|
|
123
|
+
if (meta && meta.lowPriority !== source) {
|
|
124
|
+
meta.lowPriority = source;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
prepareHostStyles() {
|
|
128
|
+
const lowPriorityContent = Object.values(this.map)
|
|
129
|
+
.map(({ lowPriority }) => lowPriority)
|
|
130
|
+
.join('\n');
|
|
131
|
+
const fullPath = path.join(this.codeRoot, HOST_STYLES_MODULE);
|
|
132
|
+
this.virtualModules.writeModule(fullPath, lowPriorityContent);
|
|
133
|
+
this.hostStylesReady = true;
|
|
134
|
+
}
|
|
112
135
|
toCodeString() {
|
|
113
136
|
const arr = Object.entries(this.map).map(([compPath, { srcPath }]) => {
|
|
114
|
-
const s = `backend.registerStyleSheetContent('${(0, helpers_1.escapeJsString)(compPath)}', require('${(0, helpers_1.escapeJsString)(srcPath)}'));`;
|
|
137
|
+
const s = `backend.registerStyleSheetContent('${(0, helpers_1.escapeJsString)(compPath)}', (require('${(0, helpers_1.escapeJsString)(srcPath)}').default||''));`;
|
|
115
138
|
return s;
|
|
116
139
|
});
|
|
140
|
+
const req = this.hostStylesReady ? `(require('./${HOST_STYLES_MODULE}').default||'')` : "''";
|
|
117
141
|
return `
|
|
118
142
|
function (backend) {
|
|
119
|
-
backend.registerStyleSheetContent('app', require('./app.wxss'))
|
|
143
|
+
backend.registerStyleSheetContent('app', ${req} + (require('./app.wxss').default||''))
|
|
120
144
|
${arr.join('')}
|
|
121
145
|
}
|
|
122
146
|
`;
|
|
@@ -126,6 +150,7 @@ class GlassEaselMiniprogramWebpackPlugin {
|
|
|
126
150
|
constructor(options) {
|
|
127
151
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
|
128
152
|
this.virtualModules = new VirtualModulesPlugin();
|
|
153
|
+
this.dev = options.dev;
|
|
129
154
|
this.path = options.path || './src';
|
|
130
155
|
this.resourceFilePattern = options.resourceFilePattern || /\.(jpg|jpeg|png|gif)$/;
|
|
131
156
|
this.defaultEntry = options.defaultEntry || 'pages/index/index';
|
|
@@ -133,6 +158,9 @@ class GlassEaselMiniprogramWebpackPlugin {
|
|
|
133
158
|
this.disableClassPrefix = options.disableClassPrefix || false;
|
|
134
159
|
}
|
|
135
160
|
apply(compiler) {
|
|
161
|
+
const devMode = this.dev === undefined
|
|
162
|
+
? compiler.options.mode === 'development' || compiler.options.mode === 'none'
|
|
163
|
+
: !!this.dev;
|
|
136
164
|
const codeRoot = path.resolve(this.path);
|
|
137
165
|
const compInfoMap = Object.create(null);
|
|
138
166
|
const resPathMap = Object.create(null);
|
|
@@ -140,7 +168,10 @@ class GlassEaselMiniprogramWebpackPlugin {
|
|
|
140
168
|
let globalStaticConfig = {};
|
|
141
169
|
let appEntry = null;
|
|
142
170
|
const depsTmplGroup = new glass_easel_template_compiler_1.TmplGroup();
|
|
143
|
-
|
|
171
|
+
// init style sheet manager
|
|
172
|
+
const virtualModules = this.virtualModules;
|
|
173
|
+
virtualModules.apply(compiler);
|
|
174
|
+
const styleSheetManager = new StyleSheetManager(this.disableClassPrefix, codeRoot, this.virtualModules);
|
|
144
175
|
// cleanup wasm modules
|
|
145
176
|
compiler.hooks.shutdown.tap(PLUGIN_NAME, () => {
|
|
146
177
|
depsTmplGroup.free();
|
|
@@ -330,8 +361,6 @@ class GlassEaselMiniprogramWebpackPlugin {
|
|
|
330
361
|
});
|
|
331
362
|
});
|
|
332
363
|
// collect virtual files
|
|
333
|
-
const virtualModules = this.virtualModules;
|
|
334
|
-
virtualModules.apply(compiler);
|
|
335
364
|
compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => {
|
|
336
365
|
// add loaders
|
|
337
366
|
webpack_1.NormalModule.getCompilationHooks(compilation).beforeLoaders.tap(PLUGIN_NAME, (loaders, mod) => {
|
|
@@ -341,12 +370,20 @@ class GlassEaselMiniprogramWebpackPlugin {
|
|
|
341
370
|
const relPath = path.relative(codeRoot, absPath).split(path.sep).join('/');
|
|
342
371
|
const compPath = relPath.slice(0, -extName.length);
|
|
343
372
|
if (extName === '.wxss') {
|
|
344
|
-
loaders.forEach((x) => {
|
|
373
|
+
loaders.forEach((x, i) => {
|
|
345
374
|
if (x.loader === exports.GlassEaselMiniprogramWxssLoader) {
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
375
|
+
if (relPath === HOST_STYLES_MODULE) {
|
|
376
|
+
loaders.splice(i, loaders.length - i);
|
|
377
|
+
}
|
|
378
|
+
else {
|
|
379
|
+
x.options = {
|
|
380
|
+
classPrefix: styleSheetManager.getScopeName(compPath),
|
|
381
|
+
compPath,
|
|
382
|
+
setLowPriorityStyles: (s, map) => {
|
|
383
|
+
styleSheetManager.setLowPriorityStyles(compPath, s, map);
|
|
384
|
+
},
|
|
385
|
+
};
|
|
386
|
+
}
|
|
350
387
|
}
|
|
351
388
|
});
|
|
352
389
|
}
|
|
@@ -356,7 +393,21 @@ class GlassEaselMiniprogramWebpackPlugin {
|
|
|
356
393
|
x.options = {
|
|
357
394
|
addTemplate(content) {
|
|
358
395
|
wxmlContentMap[compPath] = content;
|
|
359
|
-
depsTmplGroup.addTmpl(compPath, content);
|
|
396
|
+
const warnings = depsTmplGroup.addTmpl(compPath, content);
|
|
397
|
+
if (warnings && warnings.length > 0) {
|
|
398
|
+
warnings.forEach((warning) => {
|
|
399
|
+
const msgKindColored = warning.isError
|
|
400
|
+
? chalk_1.default.red('ERROR')
|
|
401
|
+
: chalk_1.default.yellow('WARN');
|
|
402
|
+
const msg = `[glass-easel-template-compiler] ${msgKindColored} ${warning.path}:${warning.startLine}:${warning.startColumn} (#${warning.code}): ${warning.message}`;
|
|
403
|
+
// eslint-disable-next-line no-console
|
|
404
|
+
if (warning.isError)
|
|
405
|
+
console.error(msg);
|
|
406
|
+
// eslint-disable-next-line no-console
|
|
407
|
+
else
|
|
408
|
+
console.warn(msg);
|
|
409
|
+
});
|
|
410
|
+
}
|
|
360
411
|
const deps = depsTmplGroup
|
|
361
412
|
.getDirectDependencies(compPath)
|
|
362
413
|
.concat(depsTmplGroup.getScriptDependencies(compPath));
|
|
@@ -376,7 +427,7 @@ class GlassEaselMiniprogramWebpackPlugin {
|
|
|
376
427
|
compilation.hooks.finishModules.tapPromise(PLUGIN_NAME, (modules) => __awaiter(this, void 0, void 0, function* () {
|
|
377
428
|
const tasks = [];
|
|
378
429
|
let indexModule;
|
|
379
|
-
const tmplGroup = new glass_easel_template_compiler_1.TmplGroup();
|
|
430
|
+
const tmplGroup = devMode ? glass_easel_template_compiler_1.TmplGroup.newDev() : new glass_easel_template_compiler_1.TmplGroup();
|
|
380
431
|
// collect compilation results
|
|
381
432
|
// eslint-disable-next-line no-restricted-syntax
|
|
382
433
|
for (const m of modules) {
|
|
@@ -418,6 +469,7 @@ class GlassEaselMiniprogramWebpackPlugin {
|
|
|
418
469
|
// write index module
|
|
419
470
|
yield Promise.all(tasks);
|
|
420
471
|
yield new Promise((resolve) => {
|
|
472
|
+
styleSheetManager.prepareHostStyles();
|
|
421
473
|
updateVirtualIndexFile(tmplGroup);
|
|
422
474
|
tmplGroup.free();
|
|
423
475
|
compilation.rebuildModule(indexModule, () => resolve());
|
|
@@ -457,7 +509,7 @@ class GlassEaselMiniprogramWebpackPlugin {
|
|
|
457
509
|
})
|
|
458
510
|
${addStyleSheet}
|
|
459
511
|
codeSpace.globalComponentEnv(index.globalObject, '${(0, helpers_1.escapeJsString)(compPath)}', () => {
|
|
460
|
-
require('./${(0, helpers_1.escapeJsString)(path.basename(compInfo.main))}')
|
|
512
|
+
module.exports = require('./${(0, helpers_1.escapeJsString)(path.basename(compInfo.main))}')
|
|
461
513
|
})
|
|
462
514
|
`);
|
|
463
515
|
};
|
|
@@ -482,14 +534,14 @@ class GlassEaselMiniprogramWebpackPlugin {
|
|
|
482
534
|
if (typeof global !== 'undefined') { return global }
|
|
483
535
|
throw new Error('The global object cannot be recognized')
|
|
484
536
|
})()
|
|
485
|
-
`;
|
|
486
|
-
const entryFooter = `
|
|
487
537
|
var initWithBackend = function (backend) {
|
|
488
538
|
var ab = env.associateBackend(backend)
|
|
489
539
|
;(${styleSheetManager.toCodeString()})(ab)
|
|
490
540
|
return ab
|
|
491
541
|
}
|
|
492
542
|
exports.initWithBackend = initWithBackend
|
|
543
|
+
`;
|
|
544
|
+
const entryFooter = `
|
|
493
545
|
var registerGlobalEventListener = function (backend) {
|
|
494
546
|
backend.onEvent((target, type, detail, options) => {
|
|
495
547
|
glassEasel.triggerEvent(target, type, detail, options)
|
package/index.ts
CHANGED
|
@@ -3,9 +3,27 @@
|
|
|
3
3
|
import { promises as fs } from 'node:fs'
|
|
4
4
|
import * as path from 'node:path'
|
|
5
5
|
import { NormalModule, type Compiler, type WebpackPluginInstance } from 'webpack'
|
|
6
|
+
import chalk from 'chalk'
|
|
6
7
|
import { TmplGroup } from 'glass-easel-template-compiler'
|
|
7
8
|
import { escapeJsString } from './helpers'
|
|
8
9
|
|
|
10
|
+
type VirtualModulePluginType = {
|
|
11
|
+
apply: (compiler: Compiler) => void
|
|
12
|
+
writeModule: (p: string, c: string) => void
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
type Warning = {
|
|
16
|
+
isError: boolean
|
|
17
|
+
level: number
|
|
18
|
+
code: number
|
|
19
|
+
message: string
|
|
20
|
+
path: string
|
|
21
|
+
startLine: number
|
|
22
|
+
startColumn: number
|
|
23
|
+
endLine: number
|
|
24
|
+
endColumn: number
|
|
25
|
+
}
|
|
26
|
+
|
|
9
27
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
10
28
|
const chokidar = require('chokidar')
|
|
11
29
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
@@ -18,8 +36,10 @@ export const GlassEaselMiniprogramWxssLoader = path.join(__dirname, 'wxss_loader
|
|
|
18
36
|
|
|
19
37
|
const PLUGIN_NAME = 'GlassEaselMiniprogramWebpackPlugin'
|
|
20
38
|
const CACHE_ETAG = 1
|
|
39
|
+
const HOST_STYLES_MODULE = '__glass_easel_host_styles__.wxss'
|
|
21
40
|
|
|
22
41
|
type PluginConfig = {
|
|
42
|
+
dev?: boolean
|
|
23
43
|
path: string
|
|
24
44
|
resourceFilePattern: RegExp
|
|
25
45
|
defaultEntry: string
|
|
@@ -66,13 +86,24 @@ const writeCache = <T>(compiler: Compiler, key: string, value: T): Promise<void>
|
|
|
66
86
|
})
|
|
67
87
|
|
|
68
88
|
class StyleSheetManager {
|
|
69
|
-
map = Object.create(null) as {
|
|
89
|
+
map = Object.create(null) as {
|
|
90
|
+
[path: string]: { scopeName: string; srcPath: string; lowPriority: string }
|
|
91
|
+
}
|
|
70
92
|
enableStyleScope = Object.create(null) as { [path: string]: boolean }
|
|
71
93
|
scopeNameInc = 0
|
|
72
94
|
disableClassPrefix: boolean
|
|
73
|
-
|
|
74
|
-
|
|
95
|
+
codeRoot: string
|
|
96
|
+
virtualModules: VirtualModulePluginType
|
|
97
|
+
hostStylesReady = false
|
|
98
|
+
|
|
99
|
+
constructor(
|
|
100
|
+
disableClassPrefix: boolean,
|
|
101
|
+
codeRoot: string,
|
|
102
|
+
virtualModules: VirtualModulePluginType,
|
|
103
|
+
) {
|
|
75
104
|
this.disableClassPrefix = disableClassPrefix
|
|
105
|
+
this.codeRoot = codeRoot
|
|
106
|
+
this.virtualModules = virtualModules
|
|
76
107
|
}
|
|
77
108
|
|
|
78
109
|
add(compPath: string, srcPath: string) {
|
|
@@ -93,6 +124,7 @@ class StyleSheetManager {
|
|
|
93
124
|
this.map[compPath] = {
|
|
94
125
|
srcPath,
|
|
95
126
|
scopeName,
|
|
127
|
+
lowPriority: '',
|
|
96
128
|
}
|
|
97
129
|
}
|
|
98
130
|
|
|
@@ -111,16 +143,33 @@ class StyleSheetManager {
|
|
|
111
143
|
return undefined
|
|
112
144
|
}
|
|
113
145
|
|
|
146
|
+
setLowPriorityStyles(compPath: string, source: string, _map: string) {
|
|
147
|
+
const meta = this.map[compPath]
|
|
148
|
+
if (meta && meta.lowPriority !== source) {
|
|
149
|
+
meta.lowPriority = source
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
prepareHostStyles() {
|
|
154
|
+
const lowPriorityContent = Object.values(this.map)
|
|
155
|
+
.map(({ lowPriority }) => lowPriority)
|
|
156
|
+
.join('\n')
|
|
157
|
+
const fullPath = path.join(this.codeRoot, HOST_STYLES_MODULE)
|
|
158
|
+
this.virtualModules.writeModule(fullPath, lowPriorityContent)
|
|
159
|
+
this.hostStylesReady = true
|
|
160
|
+
}
|
|
161
|
+
|
|
114
162
|
toCodeString() {
|
|
115
163
|
const arr = Object.entries(this.map).map(([compPath, { srcPath }]) => {
|
|
116
164
|
const s = `backend.registerStyleSheetContent('${escapeJsString(
|
|
117
165
|
compPath,
|
|
118
|
-
)}', require('${escapeJsString(srcPath)}'));`
|
|
166
|
+
)}', (require('${escapeJsString(srcPath)}').default||''));`
|
|
119
167
|
return s
|
|
120
168
|
})
|
|
169
|
+
const req = this.hostStylesReady ? `(require('./${HOST_STYLES_MODULE}').default||'')` : "''"
|
|
121
170
|
return `
|
|
122
171
|
function (backend) {
|
|
123
|
-
backend.registerStyleSheetContent('app', require('./app.wxss'))
|
|
172
|
+
backend.registerStyleSheetContent('app', ${req} + (require('./app.wxss').default||''))
|
|
124
173
|
${arr.join('')}
|
|
125
174
|
}
|
|
126
175
|
`
|
|
@@ -128,18 +177,17 @@ class StyleSheetManager {
|
|
|
128
177
|
}
|
|
129
178
|
|
|
130
179
|
export class GlassEaselMiniprogramWebpackPlugin implements WebpackPluginInstance {
|
|
180
|
+
dev?: boolean
|
|
131
181
|
path: string
|
|
132
182
|
resourceFilePattern: RegExp
|
|
133
183
|
defaultEntry: string
|
|
134
184
|
customBootstrap: boolean
|
|
135
185
|
disableClassPrefix: boolean
|
|
136
186
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
|
|
137
|
-
virtualModules = new VirtualModulesPlugin() as
|
|
138
|
-
apply: (compiler: Compiler) => void
|
|
139
|
-
writeModule: (p: string, c: string) => void
|
|
140
|
-
}
|
|
187
|
+
virtualModules = new VirtualModulesPlugin() as VirtualModulePluginType
|
|
141
188
|
|
|
142
189
|
constructor(options: Partial<PluginConfig>) {
|
|
190
|
+
this.dev = options.dev
|
|
143
191
|
this.path = options.path || './src'
|
|
144
192
|
this.resourceFilePattern = options.resourceFilePattern || /\.(jpg|jpeg|png|gif)$/
|
|
145
193
|
this.defaultEntry = options.defaultEntry || 'pages/index/index'
|
|
@@ -148,6 +196,10 @@ export class GlassEaselMiniprogramWebpackPlugin implements WebpackPluginInstance
|
|
|
148
196
|
}
|
|
149
197
|
|
|
150
198
|
apply(compiler: Compiler) {
|
|
199
|
+
const devMode =
|
|
200
|
+
this.dev === undefined
|
|
201
|
+
? compiler.options.mode === 'development' || compiler.options.mode === 'none'
|
|
202
|
+
: !!this.dev
|
|
151
203
|
const codeRoot = path.resolve(this.path)
|
|
152
204
|
const compInfoMap = Object.create(null) as {
|
|
153
205
|
[compPath: string]: { main: string; taskConfig: unknown; hasWxss: boolean }
|
|
@@ -157,7 +209,15 @@ export class GlassEaselMiniprogramWebpackPlugin implements WebpackPluginInstance
|
|
|
157
209
|
let globalStaticConfig = {} as GlobalStaticConfig
|
|
158
210
|
let appEntry: 'app.js' | 'app.ts' | null = null
|
|
159
211
|
const depsTmplGroup = new TmplGroup()
|
|
160
|
-
|
|
212
|
+
|
|
213
|
+
// init style sheet manager
|
|
214
|
+
const virtualModules = this.virtualModules
|
|
215
|
+
virtualModules.apply(compiler)
|
|
216
|
+
const styleSheetManager = new StyleSheetManager(
|
|
217
|
+
this.disableClassPrefix,
|
|
218
|
+
codeRoot,
|
|
219
|
+
this.virtualModules,
|
|
220
|
+
)
|
|
161
221
|
|
|
162
222
|
// cleanup wasm modules
|
|
163
223
|
compiler.hooks.shutdown.tap(PLUGIN_NAME, () => {
|
|
@@ -351,8 +411,6 @@ export class GlassEaselMiniprogramWebpackPlugin implements WebpackPluginInstance
|
|
|
351
411
|
})
|
|
352
412
|
|
|
353
413
|
// collect virtual files
|
|
354
|
-
const virtualModules = this.virtualModules
|
|
355
|
-
virtualModules.apply(compiler)
|
|
356
414
|
compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => {
|
|
357
415
|
// add loaders
|
|
358
416
|
NormalModule.getCompilationHooks(compilation).beforeLoaders.tap(
|
|
@@ -364,11 +422,18 @@ export class GlassEaselMiniprogramWebpackPlugin implements WebpackPluginInstance
|
|
|
364
422
|
const relPath = path.relative(codeRoot, absPath).split(path.sep).join('/')
|
|
365
423
|
const compPath = relPath.slice(0, -extName.length)
|
|
366
424
|
if (extName === '.wxss') {
|
|
367
|
-
loaders.forEach((x) => {
|
|
425
|
+
loaders.forEach((x, i) => {
|
|
368
426
|
if (x.loader === GlassEaselMiniprogramWxssLoader) {
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
427
|
+
if (relPath === HOST_STYLES_MODULE) {
|
|
428
|
+
loaders.splice(i, loaders.length - i)
|
|
429
|
+
} else {
|
|
430
|
+
x.options = {
|
|
431
|
+
classPrefix: styleSheetManager.getScopeName(compPath),
|
|
432
|
+
compPath,
|
|
433
|
+
setLowPriorityStyles: (s: string, map: string) => {
|
|
434
|
+
styleSheetManager.setLowPriorityStyles(compPath, s, map)
|
|
435
|
+
},
|
|
436
|
+
}
|
|
372
437
|
}
|
|
373
438
|
}
|
|
374
439
|
})
|
|
@@ -378,7 +443,19 @@ export class GlassEaselMiniprogramWebpackPlugin implements WebpackPluginInstance
|
|
|
378
443
|
x.options = {
|
|
379
444
|
addTemplate(content: string) {
|
|
380
445
|
wxmlContentMap[compPath] = content
|
|
381
|
-
depsTmplGroup.addTmpl(compPath, content)
|
|
446
|
+
const warnings = depsTmplGroup.addTmpl(compPath, content) as Warning[]
|
|
447
|
+
if (warnings && warnings.length > 0) {
|
|
448
|
+
warnings.forEach((warning) => {
|
|
449
|
+
const msgKindColored = warning.isError
|
|
450
|
+
? chalk.red('ERROR')
|
|
451
|
+
: chalk.yellow('WARN')
|
|
452
|
+
const msg = `[glass-easel-template-compiler] ${msgKindColored} ${warning.path}:${warning.startLine}:${warning.startColumn} (#${warning.code}): ${warning.message}`
|
|
453
|
+
// eslint-disable-next-line no-console
|
|
454
|
+
if (warning.isError) console.error(msg)
|
|
455
|
+
// eslint-disable-next-line no-console
|
|
456
|
+
else console.warn(msg)
|
|
457
|
+
})
|
|
458
|
+
}
|
|
382
459
|
const deps = depsTmplGroup
|
|
383
460
|
.getDirectDependencies(compPath)
|
|
384
461
|
.concat(depsTmplGroup.getScriptDependencies(compPath))
|
|
@@ -400,7 +477,7 @@ export class GlassEaselMiniprogramWebpackPlugin implements WebpackPluginInstance
|
|
|
400
477
|
compilation.hooks.finishModules.tapPromise(PLUGIN_NAME, async (modules) => {
|
|
401
478
|
const tasks: Promise<any>[] = []
|
|
402
479
|
let indexModule: NormalModule | undefined
|
|
403
|
-
const tmplGroup = new TmplGroup()
|
|
480
|
+
const tmplGroup = devMode ? TmplGroup.newDev() : new TmplGroup()
|
|
404
481
|
|
|
405
482
|
// collect compilation results
|
|
406
483
|
// eslint-disable-next-line no-restricted-syntax
|
|
@@ -446,6 +523,7 @@ export class GlassEaselMiniprogramWebpackPlugin implements WebpackPluginInstance
|
|
|
446
523
|
// write index module
|
|
447
524
|
await Promise.all(tasks)
|
|
448
525
|
await new Promise<void>((resolve) => {
|
|
526
|
+
styleSheetManager.prepareHostStyles()
|
|
449
527
|
updateVirtualIndexFile(tmplGroup)
|
|
450
528
|
tmplGroup.free()
|
|
451
529
|
compilation.rebuildModule(indexModule!, () => resolve())
|
|
@@ -488,7 +566,7 @@ export class GlassEaselMiniprogramWebpackPlugin implements WebpackPluginInstance
|
|
|
488
566
|
})
|
|
489
567
|
${addStyleSheet}
|
|
490
568
|
codeSpace.globalComponentEnv(index.globalObject, '${escapeJsString(compPath)}', () => {
|
|
491
|
-
require('./${escapeJsString(path.basename(compInfo.main))}')
|
|
569
|
+
module.exports = require('./${escapeJsString(path.basename(compInfo.main))}')
|
|
492
570
|
})
|
|
493
571
|
`,
|
|
494
572
|
)
|
|
@@ -515,14 +593,14 @@ export class GlassEaselMiniprogramWebpackPlugin implements WebpackPluginInstance
|
|
|
515
593
|
if (typeof global !== 'undefined') { return global }
|
|
516
594
|
throw new Error('The global object cannot be recognized')
|
|
517
595
|
})()
|
|
518
|
-
`
|
|
519
|
-
const entryFooter = `
|
|
520
596
|
var initWithBackend = function (backend) {
|
|
521
597
|
var ab = env.associateBackend(backend)
|
|
522
598
|
;(${styleSheetManager.toCodeString()})(ab)
|
|
523
599
|
return ab
|
|
524
600
|
}
|
|
525
601
|
exports.initWithBackend = initWithBackend
|
|
602
|
+
`
|
|
603
|
+
const entryFooter = `
|
|
526
604
|
var registerGlobalEventListener = function (backend) {
|
|
527
605
|
backend.onEvent((target, type, detail, options) => {
|
|
528
606
|
glassEasel.triggerEvent(target, type, detail, options)
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "glass-easel-miniprogram-webpack-plugin",
|
|
3
3
|
"description": "The webpack plugin of the glass-easel project for MiniProgram file structure",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.8.1",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "https://github.com/wechat-miniprogram/glass-easel.git"
|
|
@@ -18,16 +18,17 @@
|
|
|
18
18
|
"main": "index.js",
|
|
19
19
|
"peerDependencies": {
|
|
20
20
|
"webpack": "^5.85.0",
|
|
21
|
-
"glass-easel
|
|
22
|
-
"glass-easel": "0.
|
|
21
|
+
"glass-easel": "0.8.1",
|
|
22
|
+
"glass-easel-miniprogram-adapter": "0.8.1"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
+
"chalk": "4",
|
|
25
26
|
"chokidar": "^3.5.3",
|
|
26
27
|
"source-map": "^0.7.4",
|
|
27
28
|
"webpack-sources": "^3.2.1",
|
|
28
29
|
"webpack-virtual-modules": "^0.5.0",
|
|
29
|
-
"glass-easel-stylesheet-compiler": "0.
|
|
30
|
-
"glass-easel-template-compiler": "0.
|
|
30
|
+
"glass-easel-stylesheet-compiler": "0.8.1",
|
|
31
|
+
"glass-easel-template-compiler": "0.8.1"
|
|
31
32
|
},
|
|
32
33
|
"scripts": {
|
|
33
34
|
"build": "tsc -p .",
|
package/wxss_loader.js
CHANGED
|
@@ -1,16 +1,30 @@
|
|
|
1
1
|
/* eslint-disable */
|
|
2
2
|
|
|
3
|
+
const chalk = require('chalk')
|
|
3
4
|
const { SourceMapGenerator, SourceMapConsumer } = require('source-map')
|
|
4
5
|
const { StyleSheetTransformer } = require('glass-easel-stylesheet-compiler')
|
|
5
6
|
|
|
6
7
|
module.exports = function (src, prevMap, meta) {
|
|
7
8
|
const callback = this.async()
|
|
8
|
-
const { classPrefix } = this.query
|
|
9
|
-
const sst = new StyleSheetTransformer(this.resourcePath, src, classPrefix, 750)
|
|
9
|
+
const { classPrefix, compPath, setLowPriorityStyles } = this.query
|
|
10
|
+
const sst = new StyleSheetTransformer(this.resourcePath, src, classPrefix, 750, compPath)
|
|
11
|
+
setLowPriorityStyles(sst.getLowPriorityContent(), sst.getLowPrioritySourceMap())
|
|
12
|
+
const warnings = sst.extractWarnings()
|
|
13
|
+
if (warnings && warnings.length > 0) {
|
|
14
|
+
warnings.forEach((warning) => {
|
|
15
|
+
const msgKindColored = warning.isError
|
|
16
|
+
? chalk.red('ERROR')
|
|
17
|
+
: chalk.yellow('WARN')
|
|
18
|
+
const msg = `[glass-easel-stylesheet-compiler] ${msgKindColored} ${warning.path}:${warning.startLine}:${warning.startColumn} (#${warning.code}): ${warning.message}`
|
|
19
|
+
if (warning.isError) console.error(msg)
|
|
20
|
+
else console.warn(msg)
|
|
21
|
+
})
|
|
22
|
+
}
|
|
10
23
|
const ss = sst.getContent()
|
|
11
24
|
let map
|
|
12
25
|
if (this.sourceMap) {
|
|
13
|
-
const ssSourceMap = JSON.parse(sst.
|
|
26
|
+
const ssSourceMap = JSON.parse(sst.getSourceMap())
|
|
27
|
+
sst.free()
|
|
14
28
|
if (prevMap) {
|
|
15
29
|
const destConsumer = new SourceMapConsumer(ssSourceMap)
|
|
16
30
|
const srcConsumer = new SourceMapConsumer(prevMap)
|