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 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
- const styleSheetManager = new StyleSheetManager(this.disableClassPrefix);
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
- x.options = {
347
- classPrefix: styleSheetManager.getScopeName(compPath),
348
- relPath,
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 { [path: string]: { scopeName: string; srcPath: string } }
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
- constructor(disableClassPrefix: boolean) {
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
- const styleSheetManager = new StyleSheetManager(this.disableClassPrefix)
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
- x.options = {
370
- classPrefix: styleSheetManager.getScopeName(compPath),
371
- relPath,
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.7.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-miniprogram-adapter": "0.7.0",
22
- "glass-easel": "0.7.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.7.0",
30
- "glass-easel-template-compiler": "0.7.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.toSourceMap())
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)