Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: webpack plugin #2699

Merged
merged 30 commits into from
Oct 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
ea31cbc
feat: 新增webapck插件
Sep 24, 2023
c4ccf55
feat: 新增webapck插件
nayonglin Sep 24, 2023
e4c4a84
feat: 完成qiankun插件,简化子应用改造难度
nayonglin Sep 25, 2023
15c8445
docs: update README.md for qiankun-plugin
nayonglin Sep 25, 2023
9612df1
fix: rename plugin to @qiankunjs/webpack-plugin
nayonglin Sep 25, 2023
aa39469
fix:Revert changes to globals.ts
nayonglin Sep 25, 2023
a8894df
refactor: migrate QiankunPlugin to TypeScript
nayonglin Sep 26, 2023
94bf900
docs: update examples
nayonglin Sep 26, 2023
7e24ee7
fix: change libraryTarget to window
nayonglin Sep 26, 2023
5413104
feat: feat: plugin add automatic 'entry' attribute addition to main s…
nayonglin Sep 27, 2023
8ccbfbb
refactor: rename qiankun plugin directory to webpack-plugin
nayonglin Sep 28, 2023
86a349d
fix: delete new pluginDemo
nayonglin Oct 7, 2023
d37111e
fix: change plugin to esm
nayonglin Oct 8, 2023
4284143
docs: add comment to plugin
nayonglin Oct 8, 2023
1d95b5a
fix: eslint to plugin
nayonglin Oct 8, 2023
92cf01d
feat: add English documentation for @qiankunjs/webpack-plugin
nayonglin Oct 11, 2023
a1f2c81
feat(tests): add automated test cases for QiankunPlugin
nayonglin Oct 19, 2023
5760f84
feat(tests): add automated test cases for QiankunPlugin
nayonglin Oct 19, 2023
24ba3c2
Merge branch 'next' into feat/webpack_plugin
kuitos Oct 23, 2023
eb97056
chore(deps): update pnpm lockfile
nayonglin Oct 23, 2023
ca4f1e8
chore(deps): update pnpm lockfile
nayonglin Oct 23, 2023
070295f
chore: update lockfile
aladdin-add Oct 24, 2023
87c8293
Merge remote-tracking branch 'upstream/next' into feat/webpack_plugin
nayonglin Oct 27, 2023
06da38d
Create modern-kiwis-tap.md
kuitos Oct 27, 2023
82a1c22
fix: eslint for plugin
nayonglin Oct 27, 2023
a3b3c9d
fix: prettier for plugin
nayonglin Oct 27, 2023
aa38e16
chore: update build cmd
nayonglin Oct 29, 2023
8852c46
Update package.json
kuitos Oct 30, 2023
d06d26b
Update package.json
kuitos Oct 30, 2023
996f340
Update package.json
kuitos Oct 30, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/modern-kiwis-tap.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@qiankunjs/webpack-plugin": patch
---

feat: introduce qiankun webpack plugin
2 changes: 1 addition & 1 deletion examples/main/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ <h1>QianKun</h1>
</header>
<div class="mainapp-main">
<!-- 侧边栏 -->
<ul class="mainapp-sidemenu">
<ul class="mainapp-sidemenu">
<li data-value='react16'>React16</li>
<li data-value='react15'>React15</li>
</ul>
Expand Down
4 changes: 4 additions & 0 deletions examples/react15/webpack.config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { name } = require('./package');
const QiankunPlugin = require('../../packages/webpack-plugin/dist/cjs');



module.exports = {
entry: './index.js',
Expand Down Expand Up @@ -51,6 +54,7 @@ module.exports = {
collapseWhitespace: true,
},
}),
new QiankunPlugin(),
],
externals: {
react: 'React',
Expand Down
8 changes: 3 additions & 5 deletions examples/react16/.rescriptsrc.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
const { name } = require('./package');
const QiankunPlugin = require('../../packages/webpack-plugin/dist/cjs');


module.exports = {
webpack: config => {
config.output.library = `${name}-[name]`;
config.output.libraryTarget = 'umd';
config.output.jsonpFunction = `webpackJsonp_${name}`;
config.output.globalObject = 'window';
config.plugins.push(new QiankunPlugin());

return config;
},
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"start:example": "pnpm run build && npm run start:main && npm run start:react15",
"start:main": "cd ./examples/main && npm start",
"start:react15": "cd ./examples/react15 && npm start",
"build": "pnpm -r --filter=./packages/**/* run build",
"build": "pnpm -r --filter=./packages/**/* --filter=!./packages/**/tests/* run build",
kuitos marked this conversation as resolved.
Show resolved Hide resolved
"prerelease:alpha": "changeset pre enter alpha && changeset && changeset version",
"release:alpha": "pnpm run build && changeset publish && changeset pre exit",
"lint": "eslint packages/",
Expand Down
1 change: 1 addition & 0 deletions packages/webpack-plugin/.fatherrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from '../../.fatherrc.cjs';
53 changes: 53 additions & 0 deletions packages/webpack-plugin/README-zh.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# @qiankunjs/webpack-plugin

`@qiankunjs/webpack-plugin` 是一个为 [qiankun](https://github.com/umijs/qiankun) 微前端框架设计的 Webpack 插件,用于简化和自动化与 qiankun 集成的一些常见配置。

## 功能

- 自动设置输出库的名称和格式。
- 确保 `jsonpFunction` 名称的唯一性。
- 设置全局对象为 `window`,确保库可以在浏览器中运行。
- 自动为 html 中的入口script标签加上entry标记

## 安装

使用 npm:

```bash
npm install @qiankunjs/webpack-plugin --save-dev
```

或使用 yarn:

```bash
yarn add @qiankunjs/webpack-plugin --dev
```

## 使用

在您的 `webpack.config.js` 或其他配置文件中:

```javascript
const QiankunPlugin = require('@qiankunjs/webpack-plugin');

module.exports = {
// ... 其他配置
plugins: [
new QiankunPlugin({
packageName: 'optionalPackageName', // 可选,如果不提供,将使用 package.json 中的名称
}),
],
};
```

## 选项

- `packageName`: 指定输出库的名称。如果未提供,将使用 `package.json` 中的名称。

## 贡献

欢迎任何形式的贡献!请提交 PR 或开启 issue 讨论。

## 许可证

MIT
53 changes: 53 additions & 0 deletions packages/webpack-plugin/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# @qiankunjs/webpack-plugin

`@qiankunjs/webpack-plugin` is a Webpack plugin designed for the [qiankun](https://github.com/umijs/qiankun) micro-frontend framework, aiming to simplify and automate some common configurations when integrating with qiankun.

## Features

- Automatically sets the name and format of the output library.
- Ensures the uniqueness of the `jsonpFunction` name.
- Sets the global object to `window`, ensuring the library can run in the browser.
- Automatically adds an entry marker to the entry script tag in HTML.

## Installation

Using npm:

```bash
npm install @qiankunjs/webpack-plugin --save-dev
```

Or using yarn:

```bash
yarn add @qiankunjs/webpack-plugin --dev
```

## Usage

In your `webpack.config.js` or other configuration files:

```javascript
const QiankunPlugin = require('@qiankunjs/webpack-plugin');

module.exports = {
// ... other configurations
plugins: [
new QiankunPlugin({
packageName: 'optionalPackageName', // Optional, if not provided, the name from package.json will be used
}),
],
};
```

## Options

- `packageName`: Specifies the name of the output library. If not provided, the name from `package.json` will be used.

## Contributing

Any form of contribution is welcome! Please submit PRs or open issues for discussion.

## License

MIT
26 changes: 26 additions & 0 deletions packages/webpack-plugin/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"name": "@qiankunjs/webpack-plugin",
"version": "0.0.1",
"description": "",
"main": "./dist/cjs/index.js",
"module": "./dist/esm/index.js",
"scripts": {
"build:webpack4": "cd ./tests/webpack4 && npm run build",
"build:webpack5": "cd ./tests/webpack5 && npm run build",
"test": "npm run build && npm run build:webpack4 && npm run build:webpack5 && vitest",
"build": "father build"
},
"files": [
"dist",
"src"
],
"peerDependencies": {
"webpack": "^4.0.0 || ^5.0.0"
},
"author": "Hermanna",
"license": "MIT",
"devDependencies": {
"@types/webpack-sources": "^3.2.1",
"webpack-sources": "^3.2.3"
kuitos marked this conversation as resolved.
Show resolved Hide resolved
}
}
24 changes: 24 additions & 0 deletions packages/webpack-plugin/plugin.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import fs from 'fs';
import path from 'path';

describe('QiankunPlugin', () => {
// webpack4
it('should work with webpack 4', async () => {
// 检查产物
const htmlContent = fs.readFileSync(path.join(__dirname, 'tests/webpack4/dist/index.html'), 'utf-8');
expect(htmlContent).toContain('<script entry'); // 检查是否正确标记了 entry js

const jsChunkContent = fs.readFileSync(path.join(__dirname, 'tests/webpack4/dist/bundle.js'), 'utf-8');
expect(jsChunkContent).toContain('window.'); // 检查是否包含了 window. 关键字
});

// webpack5
it('should work with webpack 5', async () => {
// 检查产物
const htmlContent = fs.readFileSync(path.join(__dirname, 'tests/webpack5/dist/index.html'), 'utf-8');
expect(htmlContent).toContain('<script entry'); // 检查是否正确标记了 entry js

const jsChunkContent = fs.readFileSync(path.join(__dirname, 'tests/webpack5/dist/bundle.js'), 'utf-8');
expect(jsChunkContent).toContain('window.'); // 检查是否包含了 window. 关键字
});
});
91 changes: 91 additions & 0 deletions packages/webpack-plugin/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import fs from 'fs';
import path from 'path';
import type { Compiler, Configuration, Compilation } from 'webpack';
import { RawSource } from 'webpack-sources';

interface QiankunPluginOptions {
packageName?: string;
}

interface PackageJson {
name?: string;
dependencies?: Record<string, string>;
devDependencies?: Record<string, string>;
}

class QiankunPlugin {
private packageName: string;
private static packageJson: PackageJson = QiankunPlugin.readPackageJson();

constructor(options: QiankunPluginOptions = {}) {
this.packageName = options.packageName || QiankunPlugin.packageJson.name || '';
}

private static readPackageJson(): PackageJson {
const projectRoot: string = process.cwd();
const packageJsonPath: string = path.join(projectRoot, 'package.json');
return JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8')) as PackageJson;
}

private static getWebpackVersion(): string {
return QiankunPlugin.packageJson.dependencies?.webpack || QiankunPlugin.packageJson.devDependencies?.webpack || '';
}

apply(compiler: Compiler): void {
this.configureWebpackOutput(compiler);
compiler.hooks.emit.tapAsync('QiankunPlugin', (compilation: Compilation, callback: () => void) => {
this.modifyHtmlAssets(compilation);
callback();
});
}

private configureWebpackOutput(compiler: Compiler): void {
const webpackVersion = QiankunPlugin.getWebpackVersion();
const webpackCompilerOptions = compiler.options as Configuration & { output: { jsonpFunction?: string } };
if (webpackVersion.startsWith('4')) {
// webpack 4
webpackCompilerOptions.output.library = `${this.packageName}`;
webpackCompilerOptions.output.libraryTarget = 'window';
webpackCompilerOptions.output.jsonpFunction = `webpackJsonp_${this.packageName}`;
webpackCompilerOptions.output.globalObject = 'window';
webpackCompilerOptions.output.chunkLoadingGlobal = `webpackJsonp_${this.packageName}`;
} else if (webpackVersion.startsWith('5')) {
// webpack 5
webpackCompilerOptions.output.library = {
name: `${this.packageName}`,
type: 'window',
};
webpackCompilerOptions.output.libraryTarget = 'window';
webpackCompilerOptions.output.jsonpFunction = `webpackJsonp_${this.packageName}`;
webpackCompilerOptions.output.globalObject = 'window';
webpackCompilerOptions.output.chunkLoadingGlobal = `webpackJsonp_${this.packageName}`;
}
}

private modifyHtmlAssets(compilation: Compilation): void {
Object.keys(compilation.assets).forEach((filename) => {
if (filename.endsWith('.html')) {
const htmlSource = compilation.assets[filename].source();
const htmlString = typeof htmlSource === 'string' ? htmlSource : htmlSource.toString('utf-8');

const modifiedHtml = this.addEntryAttributeToScripts(htmlString);
// eslint-disable-next-line
compilation.assets[filename] = new RawSource(modifiedHtml) as any;
}
});
}

private addEntryAttributeToScripts(htmlString: string): string {
const scriptTags = htmlString.match(/<script[^>]*src="[^"]+"[^>]*><\/script>/g) || [];
const nonAsyncOrDeferScripts = scriptTags.filter((tag) => !/defer|async/.test(tag));

if (nonAsyncOrDeferScripts.length) {
const lastScriptTag = nonAsyncOrDeferScripts[nonAsyncOrDeferScripts.length - 1];
const modifiedScriptTag = lastScriptTag.replace('<script', '<script entry');
return htmlString.replace(lastScriptTag, modifiedScriptTag);
}
return htmlString;
}
}

module.exports = QiankunPlugin;
nayonglin marked this conversation as resolved.
Show resolved Hide resolved
11 changes: 11 additions & 0 deletions packages/webpack-plugin/tests/webpack4/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Webpack Test</title>
</head>
<body>
<div id="app"></div>
</body>
</html>
1 change: 1 addition & 0 deletions packages/webpack-plugin/tests/webpack4/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
console.log('Hello from test demo!');
18 changes: 18 additions & 0 deletions packages/webpack-plugin/tests/webpack4/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"name": "webpack4",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"html-webpack-plugin": "^4.5.2",
"webpack": "4",
"webpack-cli": "3"
}
}
18 changes: 18 additions & 0 deletions packages/webpack-plugin/tests/webpack4/webpack.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
const path = require('path');
const QiankunPlugin = require('../../dist/cjs');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
entry: './index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
plugins: [
new HtmlWebpackPlugin({
template: './index.html', // 指定模板文件路径
filename: 'index.html', // 输出的HTML文件名(默认为index.html)
}),
new QiankunPlugin(),
],
};
11 changes: 11 additions & 0 deletions packages/webpack-plugin/tests/webpack5/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Webpack Test</title>
</head>
<body>
<div id="app"></div>
</body>
</html>
1 change: 1 addition & 0 deletions packages/webpack-plugin/tests/webpack5/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
console.log('Hello from test demo!');
18 changes: 18 additions & 0 deletions packages/webpack-plugin/tests/webpack5/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"name": "webpack5",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"html-webpack-plugin": "^5.5.3",
"webpack": "5",
"webpack-cli": "4"
}
}
Loading