amos-build
v5.3.11
Published
the FED tool for amos team. support AMD、UMD and Commomjs
Downloads
472
Readme
amos-build
descr
- supoport webpack@1: 小于 v1.2.68
- supoport webpack@2+: 大于 v2.0.0
- update babel@7.x since v3.1.0
amos-build@5.0.3
以上版本,去掉默认module.exports
支持,混用export
和export default
的模块会存在部分bug,需要自行修改
node-sass install wizard
http://note.youdao.com/noteshare?id=7566ba03f46929e07e7fd5d91bb53013&sub=A5C0195506294B6091D2C1666ECD17D6
基于 webpack 的构建封装.
特性
- 基于 webpack 实现
- 支持通过
webpack.config.js
进行扩展 webpack 的配置项 - 支持导出
amosConfig.js、dll/*
进行自定义扩充 - @deprecated 支持 stage-0, es2015, react,sass 和 less
- 支持 env
- 支持dll,通过与amos-dll配合,快速进行构建,注意配置context为build目录
- 支持发布模式,并进行zip压缩,通过
.amosrun.config.js
进行自定义配置 - 支持 hash 模式的构建, 并生成映射表
map.json
- 插件:
plugins/*
,集成SimpleProgress、WebpackMd5Hash、AddAssetHtmlPlugin等 - 添加 worker-loader 支持 @since v2.0.19
安装
npm i amos-build --save--dev
使用
amos-build [options]
命令行参数
$ amos-build -h
Usage: amos-build [options]
Options:
-h, --help output usage information
-v, --version output the version number
-o, --output-path <path> output path
-w, --watch [delay] watch file changes and rebuild
--hash build with hash and output map.json
--publicPath <publicPath> webpack publicPath
--devtool <devtool> sourcemap generate method, default is null
--config <path> custom config path, default is webpack.config.js
--no-compress build without compress
配置扩展
如果需要对内置的 webpack 配置进行修改, 可在项目根目录新建 webpack.config.js
进行扩展.
让 webpack.config.js
输出 Function
, 比如:
const path = require("path");
module.exports = function(webpackConfig) {
webpackConfig.output.path = path.join(__dirname, './public');
return webpackConfig;
};
参数:
webpackConfig
-- 默认配置, 修改后返回新的配置
详细内容:amos-build 基本使用
amos-run
common: scss/js src/** to lib,retain original scss
singlejs: build for react components js,width js/jsx, output lib
assetscss: build for assetscss,with less、sass/scss
amosantd: for amos-antd
amosantdCustom: build for amosantdCustom,with less、css js/jsx
static
assets2dist
scss
amoscoreJs: build for amos-core js,
width js/jsx, output min.js/.css
amoscore: for amos-core,按顺序执行 ['scss', 'static', 'assets2dist', 'amoscoreJs']。
amoscoreCustom: for amos-core
security: for amos-security,
build for amos-security,width scss/sass js/jsx, output min.js/.css
amd: for amd,only copy file to
released
themes: build all themes. you should copy this files to prod dir
themes-watch: build themes and watch themes dir
commonExtra: 公共Extra,将额外文件打包进released下
src-static-all: static all
third-js: third js, 将根目录下
third、extra、plugin、plugins
文件夹之下的所有js、jsx拷贝至 lib 目录下,保留文件目录结构released: for all released, copy
dist、src/assets/**、extra/**、browser/**、*.html、amos.config.js、favicon.ico
to releaseddllreleased: for all dllreleased dev
dllreleased-test: for all dllreleased test
dllreleased-pre: for all dllreleased pre
dllreleased-prod: for all dllreleased prod
extraReleased: for all extraReleased released
extraReleased-prod: for all extraReleased released
extraReleased-test: for all extraReleased released
extraReleased-pre: for all extraReleased released
extraReleased-dev: for all extraReleased released
released2server: for all released and copy to remote server
dorobots: create robots
released2zip: zip released
amos-auto
amd: for amd,only copy file to
released
released: for all released
dllreleased: for all dllreleased
released2server: for all released and copy to remote server
released2zip: zip released
ab-tools
webpack: entry is
src/*.js
build: build
src/**/*.js、src/**/*.scss
, with reactab-babel:
src/**/*.js
non reactab-js:
src/**/*.js
non babel
amosConfig
for amos team
commonConfig
common webpack config
simpleConfig
build js with webpack
docitConfig
same as simpleConfig, and add parse md doc loader
dist
can make your single components with one bundle, example
amos-core/amos-antd
extra config
.amosrun.config.js
such as
module.exports = { // 指定zip文件名称 zip: 'released.rar', // default // 自定义配置 zip v5.0.5 版本新增 zip: { prefix: 'released', // 前缀,默认 released format: 'rar', // 文件格式,默认 rar,可选 zip date: true // 使用 date 作为后缀, false、true、datefmt [YYYYmmdd、YYYY、mmdd、HH:mm:SS] 等 年Y 月m 日d 时H 分M秒S }, // 同级目录静态文件的拷贝 默认: ['*.html', 'amos.config.js', 'favicon.ico'] extra: ['loadBMapLib.js', 'defaultSetting.js', '*.html', 'amos.config.js', 'favicon.ico'] };
simpleConfig/docitConfig/polyfillConfig
usage
- simpleConfig
/**
* webpack 打包配置文件
* @author ilex
*/
const simpleConfig = require('amos-build/lib/simpleConfig');
// ------------------------------------------------------
// 添加webpack加载别名,用于导包重定向,优化打包以及代码
// 此处需要自己进行定义
// 👻可修改
// ------------------------------------------------------
const alias = {
_MOCK: __dirname + '/src/_mock'
};
// ------------------------------------
// 入口点
// ------------------------------------
const entry = {
app: './src/entry/index.js'
};
const config = {
tpl: './tpl.html',
toFile: 'index.html',
// 设置自定义的网站 ico,默认为 amos.ico, 设置为 null 则不设置 ico
favicon: './my.ico',
entry: entry,
port: 3000,
useHot: true,
// 启用 worker `your.worker.js`,独立打包worker
enableWorker: true,
alias: alias,
sourceMap: true,
// 设置忽略压缩,默认在 prod 模式下,会自动加载 ugly 插件,该参数设置为 true时,将不再执行压缩
ignoreUgly: false,
excludeUgly: [/common\.js/, /app\.\w+\.js/], // 注意,excludeUgly 代表的是编译后生成的js文件
// Boolean|null|String, null|false|true。
// 设置为 null 则不启用 cache。
// 设置为 false 则采用系统 temp 路径。C:\\Users\\SmartRay\\AppData\\Local\\Temp\\.babel-cache
// 设置为 true 则采用当前项目目录。 -> node_modules/.cache/...
// 设置为 string 则在temp目录下新建目录。 '.cache' -> C:\\Users\\SmartRay\\AppData\\Local\\Temp\\.cache
cache: false
};
// 如果需要将指定的的 node_modules 下的包不进行 Ugly 处理,可以如下设置
// 以下设置,将会把 指定的 vender 包,打进 common.js 中
/*
const entry = {
app: './src/entry/index.js'
vender: ['react', 'react-dom', ...]
};
const config = {
...
excludeUgly: [/common\.js/, /vender\.\w+\.js/], // 注意,excludeUgly 代表的是编译后生成的js文件
};
*/
const defaultConfig = simpleConfig(config);
defaultConfig.name = 'amos-init';
module.exports = defaultConfig;
- docitConfig
同上,修改为
const docitConfig = require('amos-build/lib/docitConfig');
- polyfillConfig
同上,修改为
const polyfillConfig = require('amos-build/lib/polyfillConfig');
or const polyfillConfig = require('amos-build/lib/polyfillConfig/index.js');
- umdConfig
生成 umd
模式的模块。支持传入 cssModules
用于设置 css-loader
的 modules
属性。
webpack.config.js
const HtmlWebpackPlugin = require('amos-build/lib/plugins/HtmlWebpackPlugin');
const HtmlInlineCodePlugin = require('html-inline-code-plugin');
const resolveCwd = require('amos-build/lib/tools/resolveCwd');
const umdConfig = require('amos-build/lib/umdConfig');
const ENV = require('amos-build/lib/tools/__ENV__');
const alias = {
};
const entry = {
demo: './example/entry.umd.js'
};
const sourceMap = ENV === 'production' ? false : true
const config = {
entry,
alias,
// 仅 umdConfig 支持,表现为 output.pasth
outputPath: resolveCwd('docsite'), // 默认 为 dist 目录,注意 绝对路径
// 仅 umdConfig 支持,表现为 output.filename
filename: 'mydemo.js', // '[name].js'
library: 'mydemo',
libraryTarget: 'umd',
// 开启 css modules
// cssModules: true,
sourceMap
};
const defaultConfig = umdConfig(config);
if (ENV === 'development'){
defaultConfig.plugins.push(
// index tpl
new HtmlWebpackPlugin({
filename: 'index.html',
template: './tpl.html',
inject: true,
minify: {
removeComments: true,
collapseWhitespace: false,
removeAttributeQuotes: false
},
chunksSortMode: 'dependency'
}),
new HtmlInlineCodePlugin({
inject: 'body',
begin: false,
tag: 'script',
code: `
console.log(mydemo);
var createUI = window.mydemo;
createUI();
`
})
);
}
module.exports = defaultConfig;
entry.umd.js
import React from 'react';
import { render } from 'react-dom';
import App from './App';
import './index.scss';
export default function createUI({ container = 'app' } = {}) {
render(<App />, document.getElementById(container));
}
umd 模式新增 code-split since 5.0.1
使用默认 scripts.json
动态加入umd chunk 脚本
// 界面直接加载
fetch('/scripts.json').then(function(res){
return res.json();
}).then(function(data){
data.head.scripts.forEach(function(js){
// document.write(js);
});
data.head.urls.forEach(function(url){
var scri = document.createElement('script');
scri.src = url;
document.body.appendChild(scri);
});
data.head.tags.forEach(function(tag){
var t = document.createElement(tag.tagName);
if (tagName === 'script'){
t.src = tag.attributes.src;
}
document.body.appendChild(t);
});
data.body.scripts.forEach(function(js){
document.write(js);
});
});
// 通过代码引入
import scripts from './scripts.json';
- cjsLibConfig
默认启用使用 NodeModuleExternals
插件,生成 externals 配置。
同上,修改为
const cjsLibConfig = require('amos-build/lib/cjsLibConfig');
const cjsLibConfig = require('amos-build/lib/cjsLibConfig');
const config = {
external
};
设置 whitelist
将 node_modules
中的 required assets (i.e css files) 加入。
nodeExternals({
// load non-javascript files with extensions, presumably via loaders
whitelist: [/\.(?!(?:jsx?|json)$).{1,5}$/i],
})
plugins
ProgressWithMsg
options
|property|type|description|
| -------- | ---- | ----------- |
| messageTemplate | string | A template of progress and message shown while bundling modules. You can also use node-progress token. :msg
shows current message of webpack ProgressPlugin. |
| progressOptions | object | node-progress options to draw progress bar. defaults are shown below.
import ProgressWithMsg from 'amos-build/lib/plugins/ProgressWithMsg';
// basic use
const webpackConfig = {
entry: 'index.js',
output: {
path: 'dist',
filename: 'bundle.js'
},
plugins: [
new SimpleProgressPlugin()
]
};
// options
-- defaults
{
messageTemplate: [':bar', chalk.green(':percent'), ':msg'].join(' ')
progressOptions: {
complete: chalk.bgGreen(' '),
incomplete: chalk.bgWhite(' '),
width: 40,
total: 100,
clear: false
}
}
use dll
生成dll依赖
生成dll
webpack.dll.js
配置, 默认生成为Amoslib
const generateDll = require('amos-build/lib/dll/generateDll');
const path = require('path');
const config = {
amosLib: ['react', 'react-dom'],
// webpack.output.path dll文件生成目录
outputPath: 'dll',
// webpack.output.filename
fileName: '[name].js',
manifestPath: path.resolve(__dirname, 'dll/manifest.json'),
sourceMap: true;
};
module.exports = generateDll(config);
使用 dll
dll config (采用 amos-dll为例),注意目录为
根目录/build/amosbuildConf
, 由于amos-dll
执行时context
为build
目录
//-----------------------------------------------------------
// notice: do not modify this file content except entry/alias
// you can modify some config such as
// `showProgress/tpl/productionSourceMap/productionGzip`
// and so on
//-----------------------------------------------------------
const path = require('path');
const distPath = path.resolve(__dirname, '..', 'dist');
// const projectRoot = path.resolve(__dirname, '../');
const assetsPath = function(_path) {
return path.posix.join('static', _path);
};
// ------------------------------------
// 入口点
// 👻 可修改
// ------------------------------------
const entry = {
// app: './src/entry/index.js'
app: './src/entry/demo.js'
};
// ------------------------------------
// 添加webpack加载别名,用于导包重定向,优化打包以及代码
// 此处需要自己进行定义
// 👻可修改
// ------------------------------------
const alias = {
// MODEL: projectRoot + '/src/model',
// UTILS: projectRoot + '/src/utils',
// CONSTS: projectRoot + '/src/consts'
};
//-----------------------------------------------------------
// 👻 可修改,除非你知道该怎么修改
///-----------------------------------------------------------
module.exports = {
webpackConf: {
name: 'fireiot',
entry: entry,
alias: alias
},
showProgress: true,
context: __dirname,
tpl: 'tpl.html',
extractTextPath: assetsPath('css/[name].css?v=[contenthash:8]'),
visualizer: path.resolve(distPath, 'visualizer.html'),
prod: {
dll: {
fileName: './node_modules/amos-dll/common/prod/Amoslib.js', // 完整路径
manifest: 'amos-dll/common/prod/manifest.json',
outputPath: assetsPath('common/js'), // 生成目录
publicPath: '/static/common/js' // 注入地址
},
toFile: path.resolve(distPath, 'index.html'),
assetsRoot: distPath,
assetsSubDirectory: 'static',
assetsPublicPath: '/',
productionSourceMap: false,
// Gzip off by default as many popular static hosts such as
// Surge or Netlify already gzip all static assets for you.
// Before setting to `true`, make sure to:
// npm install --save-dev compression-webpack-plugin
productionGzip: false,
productionGzipExtensions: ['js', 'css'],
output: {
path: distPath,
filename: assetsPath('js/[name].js?v=[chunkhash:8]'),
chunkFilename: assetsPath('js/chunk.[id].js?v=[chunkhash:8]')
}
},
dev: {
dll: {
fileName: './node_modules/amos-dll/common/dev/Amoslib.js', // 完整路径
manifest: 'amos-dll/common/dev/manifest.json',
outputPath: assetsPath('common/js'), // 生成目录
publicPath: '/static/common/js' // 注入地址
},
toFile: 'index.html',
port: 9000,
assetsRoot: distPath,
assetsSubDirectory: 'static',
assetsPublicPath: '/',
staticPath: '/common',
proxyTable: {},
// CSS Sourcemaps off by default because relative paths are "buggy"
// with this option, according to the CSS-Loader README
// (https://github.com/webpack/css-loader#sourcemaps)
// In our experience, they generally work as expected,
// just be aware of this issue when enabling this option.
cssSourceMap: false,
output: {
path: distPath,
filename: assetsPath('js/[name].js'),
chunkFilename: assetsPath('js/chunk.[id].js')
}
},
test: {
dll: {
fileName: './node_modules/amos-dll/common/prod/Amoslib.js', // 完整路径
// fileName: require.resolve('amos-dll/common/prod/Amoslib.js'),
manifest: 'amos-dll/common/prod/manifest.json',
outputPath: assetsPath('common/js'), // 生成目录
publicPath: '/static/common/js' // 注入地址
},
index: path.resolve(distPath, 'index.html'),
assetsRoot: distPath,
assetsSubDirectory: 'static',
assetsPublicPath: '/',
productionSourceMap: true,
// Gzip off by default as many popular static hosts such as
// Surge or Netlify already gzip all static assets for you.
// Before setting to `true`, make sure to:
// npm install --save-dev compression-webpack-plugin
productionGzip: false,
productionGzipExtensions: ['js', 'css']
}
};
webpack.config.dll.prod.js (根目录)
const dllConfig = require('amos-build/lib/dll/prod');
const config = require('./build/amosbuildConf');
module.exports = dllConfig(config);
react-native to web
useage
- install
安装 react-native-web
$ npm install --save-dev react-native-web
- setup webpack.config.js
// webpack.config.js
const rn2webConfig = require('amos-build/lib/reactNativeToWeb');
module.exports = rn2webConfig();
// custom options
const options = {
port: 3003,
alias: alias,
sourceMap: true
};
module.exports = rn2webConfig(options);
- add index.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>ilex.h</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<div id="react-root"></div>
<script src="/dist/index.web.js"></script>
</body>
</html>
配置第三方模块按需加载 babel 加载时
since@3.1.2 版本及之后版本支持。仅支持:umdConfig、simpleConfig、cjsLibConfig
三种模式
const afModuleMapping = require('amos-framework/lib/moduleMapping');
const adModuleMapping = require('amos-antd/lib/moduleMapping');
const config = {
entry,
outputPath: resolveApp('docsite'),
filename: '[name].js',
library: 'BabelDemo',
libraryTarget: 'umd',
// 配置自定义 babel 插件
babelPlugin: [
[
require.resolve('ray-pack-toolkit/lib/babel/SplitImportPlugin'),
{
libraryName: ['amos-framework', 'amos-antd'],
customMapping: {
// 特殊处理
'amos-framework': afModuleMapping,
'amos-antd': adModuleMapping
}
}
]
],
sourceMap: false
};
注意事项
simpleConfig/docitConfig/polyfillConfig
等,均设置 publicPath
为服务器根路径,如果需要使用相对路径,或其他路径,可以自定义 output 或者,删掉改属性。主要表现在,webpack 打包时,注入的文件路径。
<script type="text/javascript" src="/common.js">
如果去掉 publicPath
,则最终的 html 如下:
<script type="text/javascript" src="common.js">
实现方式:
var docitConfig = require('amos-build/lib/docitConfig');
// ... 配置信息
var defaultConfig = docitConfig(config);
// 删除 publicPath
delete defaultConfig.output.publicPath;
// 修改 publicPath
defaultConfig.output.publicPath = '.'; // <script type="text/javascript" src="./common.js">
常见错误剖析
在开发模式下,开启split,部分chunk file hash值并未改变,但是内容却变了
剖析:该问题,是由webpack进行模块分割时,经常会出现的bug
解决:
const webpack = require('webpack');
// 方式一:将系统中默认采用 id 命名方式,改为 NamedModulesPlugin
defaultConfig.plugins.push(
// new webpack.HashedModuleIdsPlugin();
// 非必须
// new webpack.NamedModulesPlugin();
new webpack.NamedChunksPlugin((chunk) => {
if (chunk.name) {
return chunk.name;
}
return chunk.mapModules(m => m.id).join('_');
}),
);
// 方式二:采用 hash 方式, 不推荐,因为每次都会更改 hash 值。原始采用的是 chunkhash
defaultConfig.output.filename = '[name].[hash].js';
defaultConfig.output.chunkFilename = 'chunk/[name].[hash].js';
在 3.0.12 及其之后版本,新增 useHash
来默认启用 hash 的方式创建文件名,仅在 production
模式下起效。
const simpleConfig = require('amos-build/lib/simpleConfig');
const config = {
...
useHash: true
};
const defaultConfig = simpleConfig(config);
externals 说明
use a regex in the Webpack config
Webpack allows inserting regex in the externals array, to capture non-relative modules:
{
externals: [
// Every non-relative module is external
// abc -> require("abc")
/^[a-z\-0-9]+$/
]
}
// 自定义
{
externals: [
function(context, request, callback) {
if (/^(amos-|ray-)/i.test(request)){
// return callback(null, 'umd ' + request);
return callback(null, 'commonjs ' + request);
}
callback();
},
/^(react|react-dom|prop-types|dt2react|classnames|moment)$/i,
/^(amos-|ray-)/i,
]
}
这种方式,会强制将所有的 non-relative requires 剥离,如果使用了
alias
配置,将不会进行bundled
。
采用 NodeMoudleExternals
实现仅仅剥离 node_modules
中的模块。
webpack 5.x 之后版本
手动添加 node 依赖支持:
mqtt-packet/writeToStream.js
依赖 safe-buffer 和 process-nextick-args
,将 buffer 和 process
设置为 amos-mqtt 的强依赖。
mqtt (readable-stream)
jszip/lib/readable-stream-browser.js
(stream)Buffer:
buffer
mqttamos-mqtt
中将其声明为强依赖process:
process/browser
mqttamos-mqtt
中将其声明为强依赖stream:
stream-browserify
jszipamos-viz
中将其声明为强依赖
v5.0.3
及之前版本,多次通过@import
引入重复的 css 或者 scss 将会导致最终打包生成多份样式。v5.0.4
解决重复引入样式问题,及工程中无.stylelintrc.json
文件问题。
新增 zipConfig
since 5.0.3 版本之后,新增 zipConfig。
支持 simpleConfig、umdConfig、docitConfig、cjsLibConfig、themeConfig、MFConfig
const config = {
zipConfig: {
// 复制
copy: [
{ source: 'dist/**', destination: 'released' },
{ source: 'amos.config.js', destination: 'released/amos.config.js' },
{ source: 'src/assets/**', destination: 'released/src/assets' }
],
// 删除文件夹或者文件
delete: ['zip/**'],
// 创建文件夹
mkdir: ['zip/'],
// 压缩
// options 配置 https://www.archiverjs.com/archiver
archive: [
{ source: 'released/**', destination: 'zip/released.zip' },
{ source: 'amos.config.js', destination: 'zip/conf.zip' },
{ source: 'dist/robot.txt', destination: 'zip/robot.zip' },
{ source: 'dist/**', destination: 'zip/dist.zip', format: 'tar' },
// 开启gzip
{ source: 'dist/**', destination: 'zip/dist.zip', format: 'tar', options: {
gzip: true,
gzipOptions: {
level: 1,
},
globOptions: {
nomount: true,
}
} }
]
}
};
案例:
组态工程中,将sdkroot 目录进行打包,同时将 scripts.json
文件独立拷贝
注意,打包之前,需要手动先删除
external/morphic/
目录,可直接在组态 npm scripts 中新增"cleanSdk": "rimraf sdkroot external/morphic"
const config = {
...
zipConfig: {
copy: [
{ source: 'sdkroot/scripts.json', destination: 'external/morphic/scripts.json' }
],
archive: [
{ source: 'sdkroot', destination: 'external/morphic/sdk.zip' }
]
}
...
};
新增 gzip
since v5.1.1
版本之后,新增 gzip
配置项,可以在打包时开启 gzip 特性。
gzip
也可以直接使用 nginx
中的 gzip
特性,无需打包处理。
const config = {
...
gzip: true // 简单使用,采用默认 `test: /\.js(\?.*)?$/i`
gzip: {
test: /\.js(\?.*)?$/i,
include: /\/includes/,
exclude: /\/excludes/,
algorithm: "gzip",
compressionOptions: {
level: 9
},
threshold: 0,
minRatio: 0.8,
filename: '[path][base].gz',
deleteOriginalAssets: false
}
};
nginx 开启 gzip
#开启和关闭gzip模式
gzip on|off;
#gizp压缩起点,文件大于1k才进行压缩
gzip_min_length 1k;
# gzip 压缩级别,1-9,数字越大压缩的越好,也越占用CPU时间
gzip_comp_level 5;
# 进行压缩的文件类型。
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript;
#nginx对于静态文件的处理模块,开启后会寻找以.gz结尾的文件,直接返回,不会占用cpu进行压缩,如果找不到则不进行压缩
gzip_static on|off
# 是否在http header中添加Vary: Accept-Encoding,建议开启
gzip_vary on;
# 设置压缩所需要的缓冲区大小,以4k为单位,如果文件为7k则申请2*4k的缓冲区
gzip_buffers 2 4k;
# 设置gzip压缩针对的HTTP协议版本
gzip_http_version 1.1;
MFConfig
采用 ModuleFederation 模式,创建 config 配置脚本。MfConfig 是 simpleConfig 的产物扩展功能而来
新增配置参数: mfConfig、mfMode
const MFConfig = require('amos-build/lib/MFConfig');
const { getReactMf, getShared } = require('amos-build/lib/tools/pluginConfig');
const { dependencies: deps, devDependencies: devps } = require('./package.json');
// both 模式
const mfOption = {
name: 'amosasp',
// 默认 library,可以不传入
library: { type: 'var', name: 'amosasp' },
filename: 'remoteEntry.js',
remotes: __ENV__ === 'production' ? mfInfo.remotes.prod : mfInfo.remotes.dev,
exposes: {
'./amos-xxx': './src/xxx.js'
},
shared: {
...getReactMf(deps.react, deps['react-dom'])
}
};
// host 模式
const mfOption = {
remotes: __ENV__ === 'production' ? mfInfo.remotes.prod : mfInfo.remotes.dev,
shared: {
...getReactMf(deps.react, deps['react-dom'])
}
};
// remote 模式
const mfOption = {
name: 'amosaf',
// 默认 library,可以不传入
library: { type: 'var', name: 'amosaf' },
filename: 'remoteEntry.js',
exposes: {
'./amos-xxx': './src/xxx.js'
},
shared: {
...getReactMf(devps.react, devps['react-dom']),
...getShared([
// 'amos-tool', 'crispfit-ui', 'domtool', 'dt2react'
'amos-tool', 'dt2react'
], deps)
}
};
const config = {
...
mfConfig: mfOption,
mfMode: 'both', // remote、host
...,
replacer: {
pkgs: [],
rules: [
{ src: 'amos-xxx', dest: 'amosaf/amos-xxx' },
]
}
};
// 搭配 replacer 进行使用,可以编译时替换目录
umdConfig、cjsLibConfig
想直接使用 remotes 模块,采用如下方式即可:
const umdConfig = require('amos-build/lib/umdConfig');
const { getReactMf, getShared, invokeMFRemotes } = require('amos-build/lib/tools/pluginConfig');
const { dependencies: deps, devDependencies: devps } = require('./package.json');
// host 模式
const mfOption = {
remotes: __ENV__ === 'production' ? mfInfo.remotes.prod : mfInfo.remotes.dev,
shared: {
...getReactMf(deps.react, deps['react-dom'])
}
};
const config = {
...,
replacer: {
pkgs: [],
rules: [
{ src: 'amos-xxx', dest: 'amosaf/amos-xxx' },
]
}
};
const defaultConfig = umdConfig(config);
invokeMFRemotes(defaultConfig, mfOption);
module.exports = defaultConfig;
教程系列
项目中使用 .umdrc.js 配置文件
.umdrc.js
位于项目根目录
const { commonExternals } = require('amos-build/lib/tools/pluginConfig');
// 通过 commonExternals 快速创建 umdConfig
const umdConfig = commonExternals([
'react', 'react-dom', 'amos-react-router', 'prop-types', 'amos-antd', 'amos-framework', 'xgplayer', 'xgplayer-flv', 'xgplayer-hls', 'amos-designer',
// studio asp remote 需要
'base-r3d', 'amos-gojs'
]);
module.exports = {
// dir 和 list 用于从 pkg 中拷贝 mf 包
dir: 'website/umd_lib',
list: [
...umdConfig.list,
// codemirror、ace
{ pkg: 'amos-code-actuator', umd: 'dist' },
// tinymce quill
{ pkg: 'amos-richtext', umd: 'umd' },
// echarts all
{ pkg: 'amos-viz', umd: 'umd' }
],
externals: {
...umdConfig.externals,
'amos-code-actuator/lib/codemirror/umd': 'ActuatorCM',
// ace editor
'amos-code-actuator/lib/ace/umd': 'ActuatorACE',
'amos-viz/lib/echarts/umd': 'VizEcharts',
// rich text
'amos-richtext/lib/quill/umd': 'RichTextQuill',
'amos-richtext/lib/tinymce/umd': 'RichTextMCE'
},
scripts: {
// 注意,数组中,靠前的后加载
head: [
...umdConfig.scripts.head
],
body: [
...umdConfig.scripts.body,
"amos-code-actuator/codemirror.umd.js",
"amos-code-actuator/ace.umd.js",
"amos-viz/viz-echarts.umd.js",
"amos-richtext/tinymce.umd.js",
"amos-richtext/quill.umd.js",
]
},
// link 样式可以, 均放在 head
links: [
...umdConfig.links
]
};
根目录的 webpack.config.js
umd_lib
内容可采取线上模块,也可采用 amos-plugin --umd --umd-r
命令动态生成
/**
* webpack 打包配置文件
* @author ilex
*/
const MFConfig = require('amos-build/lib/MFConfig');
const { getRCConfigInfo, getOuterScripts, getDynamicTags } = require('amos-build/lib/tools/pluginConfig');
const HtmlInlineCodePlugin = require('html-inline-code-plugin');
const umdRc = getRCConfigInfo('umd', '');
const defaultConfig = MFConfig({ ... });
// 设置 外部脚本配置
defaultConfig.externals = umdRc.externals;
// prefix 可以填写线上已发布目录,如 `http://172.16.10.72/umd_lib/`,此时无需执行相关 umd copy
// 给 html 加入 externals 脚本
const headLibs = getOuterScripts(umdRc.scripts.head, {
inject: 'head',
prefix: '/umd_lib/'
});
const bodyLibs = getOuterScripts(umdRc.scripts.body, {
inject: 'body',
prefix: '/umd_lib/'
});
const headLinks = getDynamicTags(umdRc.links, {
inject: 'head',
prefix: '/umd_lib/'
});
defaultConfig.plugins.push(
new HtmlInlineCodePlugin([
...headLibs,
...bodyLibs,
...headLinks
])
);
项目中将多个lib挂在同一个 lib name 下
/**
* webpack 打包配置文件
* 测试 mods 分离
* @author ilex
*/
const umdConfig = require('amos-build/lib/umdConfig');
const { getRCConfigInfo } = require('amos-build/lib/tools/pluginConfig');
const resolveCwd = require('amos-build/lib/tools/resolveCwd');
const __ENV__ = require('amos-build/lib/tools/__ENV__');
const coms = require('./test/mfcard/entry.js');
const umdRc = getRCConfigInfo('umd', '.');
function genConfig(entry, libname, analyzer) {
const config = {
entry,
outputPath: resolveCwd('mfcarddist'),
filename: '[name].js',
//
library: libname,
libraryTarget: 'umd',
libraryExport: 'default',
// 启动 WebWorker
enableWorker: true,
// ignoreUgly: true,
sourceMap: __ENV__ === 'production' ? false : true
};
// 分析 module 模块
if (analyzer) {
config.analyzer = {
// umd 模式下,使用 static 模式
analyzerMode: 'static'
};
}
const ucg = umdConfig(config);
ucg.name = 'amos-ag-mfcard';
// 设置 外部脚本配置
ucg.externals = umdRc.externals;
return ucg;
}
const comsConfig = (Object.keys(coms) || []).reduce((prev, curr) => {
prev.push(genConfig({
[curr]: coms[curr]
}, ['___$agModules', '[name]']));
return prev;
}, []);
module.exports = [
...comsConfig
];
项目中将自动扫描并添加entry
- 将当前目录下的所有
*.js
添加到 entry 中
entry.js 目录: mfcard/entry.js
// 自动添加 entry,必须要保证 key 和 文件名一样才可以
const glob = require('glob');
const path = require('path');
const ignore = [
'**/node_modules/**',
'./mfcard/_globalParams.js',
'./mfcard/entry.js',
'./mfcard/myentry.js'
];
// 使用glob模块来匹配文件
const files = glob.sync('./mfcard/*.js', { ignore });
// 创建一个entry对象
const entries = {};
// 遍历所有匹配到的文件,将它们设置为entry
files.forEach(file => {
const f = path.parse(file);
// const fname = path.basename(file);
// const name = fname.replace('.js', '');
// 直接使用 path.resolve 获取全路径
// const allpath = path.resolve(file);
// 如果使用 require.resolve 获取全路径,需要定位到 sync 中指定的根目录下。
const entryPath = require.resolve(file.replace('./mfcard', '.'));
// 全小写 (需要与 mfcard组件定义的 key 保持一致)
entries[f.name.toLowerCase()] = entryPath;
});
module.exports = entries;
- 将 mfcard 目录中的所有满足条件的
index.js
添加到entry
中
const glob = require('glob');
// 使用glob模块来匹配文件
const files = glob.sync('./mfcard/**/index.js', { ignore: ['**/node_modules/**', './mfcard/__test__/**', './mfcard/index.js'] });
const reg = /^\.\/([^_][\w-]+\/)+index\.(js|jsx)?$/;
// 创建一个entry对象
const entries = {};
// 遍历所有匹配到的文件,将它们设置为 entry (必须要约定entry name 为 index.js 父级文件夹名)
files.forEach(file => {
const match = file.match(reg);
const name = match[1].replace('/', '');
// 采用 `require.resolve` 处理全路径时,根据脚本运行位置,有可能需要去除部分前缀
const fp = file.replace('./mfcard', '.');
const entryPath = require.resolve(fp);
// 采用 path.resolve 直接可以获取到全路径
// const entryPath = path.resolve(file);
entries[name] = entryPath;
});
module.exports = entries;
全局字符串替换
// build 时间
_AMOS_BUILD_EXECUTE_TIME_
// 全局统一版本好
__GLOBAL_VERSION_
// 使用方式
console.log('amos build time:', _AMOS_BUILD_EXECUTE_TIME_)
window.__global_version = __GLOBAL_VERSION_;
BUGS
启用 ModuleFederationPlugin 时,babel-loader 设置 presets 存在的bug
Uncaught (in promise) Error: Shared module is not available for eager consumption: webpack/sharing/consume/default/react/react
[
resolve('@babel/preset-react'),
[
resolve('@babel/preset-env'),
{
// https://babeljs.io/docs/en/babel-preset-env#modules
// 设置为 false 将会保留 es 模块。将imports和exports让webpack去处理
modules: 'amd', // 该值仅当设置为 `amd umd auto false` 时,才能使用 ModuleFederationPlugin
targets: {
browsers: envBrowsers
}
}
]
];