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

支持对依赖的内容进行转换 #109

Merged
merged 3 commits into from
Sep 12, 2019
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
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
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ npm 包与 docker 镜像的对比,优点:

- extractVendor

控制是否抽取固定依赖(vendor),要求传入一个入口文件名(`entry`)该 entry 的内容将会被认为是固定依赖,被抽取到单独的文件中,而不会重复出现在每个 entry 的结果文件里。一方面它可以更精确地实现抽取公共内容的效果,另外一方面,在 vendor entry 内容不变的情况下,结果文件本身的 hash 不会改变,可以更充分地利用浏览器缓存。典型的 vendor entry 的内容形如:
控制抽取固定依赖(vendor)的行为,要求传入一个入口文件名(`entry`)以启用;该 entry 的内容将会被认为是固定依赖,被抽取到单独的文件中,而不会重复出现在每个 entry 的结果文件里。一方面它可以更精确地实现抽取公共内容的效果,另外一方面,在 vendor entry 内容不变的情况下,结果文件本身的 hash 不会改变,可以更充分地利用浏览器缓存。典型的 vendor entry 的内容形如:

```javascript
import 'react'
Expand All @@ -194,7 +194,11 @@ npm 包与 docker 镜像的对比,优点:

- compressImage

是否压缩图片(png, jpe?g, gif)
是否压缩图片(png, jpe?g, gif),`true` 启用,`false` 禁用

- transformDeps

是否对第三方依赖包(node_modules 中的内容)的 Javascript 内容进行转换(builder 默认会跳过对依赖包 Javascript 内容的转换,以提升构建效率)。这里传入 `true` 表示全部进行转换,`false` 则全部不转换;也可以传入包名列表来指定需要转换的第三方依赖包,如传入 `[ "react", "mobx" ]`,表示仅对包 react 与包 mobx 的 Javascript 内容进行转换

* test

Expand Down
14 changes: 10 additions & 4 deletions lib/utils/build-conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,25 @@ const paths = require('./paths')
const logger = require('./logger')

/**
* The complete Triforce, or one or more components of the Triforce.
* @typedef {object} Engines
* @property {string} builder - required builder version range
*/

/**
* The complete Triforce, or one or more components of the Triforce.
* @typedef {object} TestConfig
* @property {string[]} setupFiles - files to run before each test
* @property {object} moduleNameMapper - map for modules, like https://facebook.github.io/jest/docs/en/configuration.html#modulenamemapper-object-string-string
*/

/**
* The complete Triforce, or one or more components of the Triforce.
* @typedef {object} Optimization
* @property {boolean} extractCommon 是否抽取 entries 间的公共内容到单独的文件中
* @property {string} extractVendor 抽取固定依赖行为
* @property {boolean} compressImage 是否压缩图片
* @property {boolean|string[]} transformDeps 是否对第三方依赖包的 Javascript 内容进行转换
*/

/**
* @typedef {object} BuildConfig
* @property {string} extends - target config to extend
* @property {string} publicUrl
Expand All @@ -38,9 +43,10 @@ const logger = require('./logger')
* @property {string[]} transformIncludes - 构建时需要被包含进来(被 transformer 处理)的第三方内容
* @property {object} envVariables - 注入到代码中的环境变量
* @property {object} isomorphicTools - ssr 相关的 webpack-isomorphic-tools config
* @property {object} optimization
* @property {Optimization} optimization
* @property {object} devProxy
* @property {object} deploy
* @property {object} targets
* @property {TestConfig} test
* @property {Engines} engines
*/
Expand Down
60 changes: 43 additions & 17 deletions lib/webpack-config/addons/add-transform.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,16 @@ const makeBabelPlugin = plugin => (
: [adaptBabelPluginName(plugin[0]), ...plugin.slice(1)]
)

// 修改 babel-loader 的配置以适配 webpack2 (enable tree-shaking,由 webpack 来做 module 格式的转换)
// 添加 preset-env 的 targets
// 找到 env 这个 preset,添加 { "modules": false, targets }
// 注意后续可能要修改这边逻辑,考虑会对 import / export 进行转换的不一定只有 env 这个 preset
/**
* @desc 修改 babel-loader 的配置以适配 webpack2 (enable tree-shaking,由 webpack 来做 module 格式的转换)
* 添加 preset-env 的 targets
* 找到 env 这个 preset,添加 { "modules": false, targets }
* 注意后续可能要修改这边逻辑,考虑会对 import / export 进行转换的不一定只有 env 这个 preset
* @param {object} options babel options
* @param {object} targets babel env targets: https://babeljs.io/docs/en/babel-preset-env#targets
* @return {object}
* TODO: 检查现在 webpack4 是不是还需要 modules: false 的逻辑
*/
const makeBabelLoaderOptions = (options, targets) => {
if (!options) {
return options
Expand Down Expand Up @@ -87,7 +93,7 @@ const adaptLoader = ({ loader, options }) => {
return loaderObj
}

const makeRule = (extension, context, ...loaderList) => {
const makeRule = (extension, context, exclude, ...loaderList) => {
const rule = {
test: makeExtensionPattern(extension),
use: loaderList.map(adaptLoader)
Expand All @@ -104,10 +110,10 @@ const makeRule = (extension, context, ...loaderList) => {
rule.issuer = makeExtensionPattern(context)
}

// 针对后缀为 js 的 transform,控制范围(不对依赖做转换)
if (extension === 'js') {
rule.exclude = /(node_modules)/
if (exclude != null) {
rule.exclude = exclude
}

return rule
}

Expand Down Expand Up @@ -145,12 +151,24 @@ function makePostcssOptions({ autoprefixerOptions }) {
}
}

/**
* @desc 构造处理 Javascript 内容时排除依赖用的正则
* @param {boolean|string[]} transformDeps 是否排除依赖,或需要被处理(不应该被排除)的依赖包名
* @return {RegExp}
*/
function makeJsExcludePattern(transformDeps) {
if (Array.isArray(transformDeps)) {
return new RegExp(`node_modules/(?!(${transformDeps.join('|')})/).*`)
}
return transformDeps ? null : /node_modules\//

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

会不会这样比较好懂

if (typeof ** === boolean) {
  return ** ? null : /node_modules\//
}
return **

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里主要是考虑了下值为 undefined 等的边际情况

}

module.exports = (config, key, transform, buildConfig, post) => {
if (!key || typeof key !== 'string') {
throw new TypeError(`Invalid transform key: ${JSON.stringify(key)}`)
}

const { targets } = buildConfig
const { targets, optimization } = buildConfig
const [extension, context] = key.split('@')

const isTesting = buildEnv.get() === buildEnv.test
Expand All @@ -171,6 +189,13 @@ module.exports = (config, key, transform, buildConfig, post) => {
return config
}

// 针对后缀为 js 的 transform,控制范围(不对依赖做转换)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

为啥特意限制一下呀,这个是不是太 hack 了。。毕竟从表面上看并看不出会有这个限制。。

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@codingstar 你指哪个限制?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

就是不 transform 后缀为 js 的文件。。。0 0 @nighca

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@codingstar 是工程上的常见优化手段,基于两个前提:

  1. 很多包 release 的时候会做一遍 compile 的事情,甚至其内容可能不能重新被 compile,见 PR 中提到的 TypeError: _typeof is not a function 问题
  2. babel 很慢,node_modules 内容很多,因此会大大影响构建效率

const exclude = (
extension === 'js'
? makeJsExcludePattern(optimization.transformDeps)
: null
)

switch(transform.transformer) {
case transforms.css:
case transforms.less:
Expand Down Expand Up @@ -212,7 +237,7 @@ module.exports = (config, key, transform, buildConfig, post) => {

config = update(config, {
module: { rules: {
$push: [makeRule(extension, context, ...loaders)]
$push: [makeRule(extension, context, exclude, ...loaders)]
} }
})
break
Expand All @@ -223,7 +248,7 @@ module.exports = (config, key, transform, buildConfig, post) => {
config = addDefaultExtension(config, extension)
config = update(config, {
module: { rules: {
$push: [makeRule(extension, context, { loader: 'babel', options: babelLoaderOptions })]
$push: [makeRule(extension, context, exclude, { loader: 'babel', options: babelLoaderOptions })]
} }
})
break
Expand All @@ -237,7 +262,7 @@ module.exports = (config, key, transform, buildConfig, post) => {
config = addDefaultExtension(config, extension)
config = update(config, {
module: { rules: {
$push: [makeRule(extension, context, {
$push: [makeRule(extension, context, exclude, {
loader: 'babel',
options: makeBabelLoaderOptions(
makeReactBabelOptions(transformConfig.babelOptions),
Expand Down Expand Up @@ -276,6 +301,7 @@ module.exports = (config, key, transform, buildConfig, post) => {
$push: [makeRule(
extension,
context,
exclude,
{ loader: 'babel', options: makeBabelLoaderOptions(babelOptions, targets) },
{ loader: 'ts', options: tsLoaderOptions }
)]
Expand All @@ -289,7 +315,7 @@ module.exports = (config, key, transform, buildConfig, post) => {
config = addDefaultExtension(config, extension)
config = update(config, {
module: { rules: {
$push: [makeRule(extension, context, { loader: transform.transformer, options: transform.config })]
$push: [makeRule(extension, context, exclude, { loader: transform.transformer, options: transform.config })]
} }
})
break
Expand All @@ -299,7 +325,7 @@ module.exports = (config, key, transform, buildConfig, post) => {
config = update(config, {
module: { rules: {
$push: [
makeRule(extension, context, {
makeRule(extension, context, exclude, {
loader: 'file',
options: { name: 'static/[name]-[hash].[ext]' }
})
Expand Down Expand Up @@ -342,7 +368,7 @@ module.exports = (config, key, transform, buildConfig, post) => {
config = update(config, {
module: { rules: {
$push: [
makeRule(extension, context, {
makeRule(extension, context, exclude, {
loader: 'vue',
options
})
Expand All @@ -356,7 +382,7 @@ module.exports = (config, key, transform, buildConfig, post) => {
config = update(config, {
module: { rules: {
$push: [
makeRule(extension, context, {
makeRule(extension, context, exclude, {
loader: 'svg-sprite',
options: {
// TODO:
Expand All @@ -375,7 +401,7 @@ module.exports = (config, key, transform, buildConfig, post) => {
default: {
config = update(config, {
module: { rules: {
$push: [makeRule(extension, context, { loader: transform.transformer, options: transform.config })]
$push: [makeRule(extension, context, exclude, { loader: transform.transformer, options: transform.config })]
} }
})
}
Expand Down
3 changes: 2 additions & 1 deletion preset-configs/angular.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
"@babel/plugin-syntax-import-meta",
"@babel/plugin-proposal-class-properties",
"@babel/plugin-proposal-json-strings"
]
],
"sourceType": "unambiguous"
}
},
"html": "html"
Expand Down
6 changes: 4 additions & 2 deletions preset-configs/default.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@
"@babel/plugin-syntax-import-meta",
"@babel/plugin-proposal-class-properties",
"@babel/plugin-proposal-json-strings"
]
],
"sourceType": "unambiguous"
}
},
"css": "css",
Expand Down Expand Up @@ -67,7 +68,8 @@
"optimization": {
"extractCommon": true,
"extractVendor": "",
"compressImage": false
"compressImage": false,
"transformDeps": false
},
"devProxy": {},
"deploy": {
Expand Down
6 changes: 4 additions & 2 deletions preset-configs/react.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
"@babel/plugin-syntax-import-meta",
"@babel/plugin-proposal-class-properties",
"@babel/plugin-proposal-json-strings"
]
],
"sourceType": "unambiguous"
}
}
},
Expand All @@ -36,7 +37,8 @@
"@babel/plugin-syntax-import-meta",
"@babel/plugin-proposal-class-properties",
"@babel/plugin-proposal-json-strings"
]
],
"sourceType": "unambiguous"
}
}
},
Expand Down