Generate tsconfig once instead of on every webpack invocation
Avoids any potential race condition with parallel webpack invocations
This commit is contained in:
@@ -28,6 +28,8 @@ brave_common_web_compile_inputs = [
|
|||||||
|
|
||||||
# webpack config changes warrant a re-build of all webpack builds
|
# webpack config changes warrant a re-build of all webpack builds
|
||||||
rebase_path("../webpack/webpack.config.js"),
|
rebase_path("../webpack/webpack.config.js"),
|
||||||
|
rebase_path("../webpack/gen-webpack-grd.js"),
|
||||||
|
rebase_path("../webpack/path-map.js"),
|
||||||
rebase_path("../webpack/webpack-plugin-depfile.js"),
|
rebase_path("../webpack/webpack-plugin-depfile.js"),
|
||||||
|
|
||||||
# typescript config changes warrant a re-build of all typescript builds
|
# typescript config changes warrant a re-build of all typescript builds
|
||||||
@@ -83,6 +85,7 @@ template("transpile_web_ui") {
|
|||||||
|
|
||||||
# make sure rebuilds when common files change
|
# make sure rebuilds when common files change
|
||||||
inputs = brave_common_web_compile_inputs
|
inputs = brave_common_web_compile_inputs
|
||||||
|
inputs += [ "$root_gen_dir/tsconfig-webpack.json" ]
|
||||||
if (defined(invoker.inputs)) {
|
if (defined(invoker.inputs)) {
|
||||||
inputs += invoker.inputs
|
inputs += invoker.inputs
|
||||||
}
|
}
|
||||||
@@ -90,7 +93,7 @@ template("transpile_web_ui") {
|
|||||||
deps = [
|
deps = [
|
||||||
# Ensure chrome://resources/js file and typescript definitions are
|
# Ensure chrome://resources/js file and typescript definitions are
|
||||||
# generated
|
# generated
|
||||||
"//ui/webui/resources:library",
|
"//brave/components/webpack:generate_tsconfig",
|
||||||
]
|
]
|
||||||
if (defined(invoker.deps)) {
|
if (defined(invoker.deps)) {
|
||||||
deps += invoker.deps
|
deps += invoker.deps
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
action("generate_tsconfig") {
|
||||||
|
script = "//brave/script/generate-tsconfig.py"
|
||||||
|
deps = [
|
||||||
|
# Ensure chrome://resources/js file and typescript definitions are
|
||||||
|
# generated
|
||||||
|
"//ui/webui/resources:library",
|
||||||
|
]
|
||||||
|
inputs = [
|
||||||
|
"gen-tsconfig.js",
|
||||||
|
"path-map.js",
|
||||||
|
]
|
||||||
|
outputs = [ "$root_gen_dir/tsconfig-webpack.json" ]
|
||||||
|
args = [ "--root_gen_dir=" + rebase_path(root_gen_dir) ]
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
const fs = require('fs-extra')
|
||||||
|
const path = require('path')
|
||||||
|
const pathMap = require('./path-map')
|
||||||
|
|
||||||
|
const srcPath = path.resolve(__dirname, '../../../')
|
||||||
|
const braveSrcPath = path.join(srcPath, 'brave')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a tsconfig.json file in the gen/ directory
|
||||||
|
* so that typescript can import files from cthe current build's
|
||||||
|
* gen/ directory (e.g. mojom-generated JS).
|
||||||
|
*
|
||||||
|
* @param {*} [atPath=process.env.ROOT_GEN_DIR]
|
||||||
|
* @returns void
|
||||||
|
*/
|
||||||
|
async function createGenTsConfig (atPath = process.env.ROOT_GEN_DIR) {
|
||||||
|
const configExtendsFrom = path.relative(
|
||||||
|
atPath,
|
||||||
|
path.join(braveSrcPath, 'tsconfig-webpack.json')
|
||||||
|
)
|
||||||
|
const tsConfigPath = path.join(atPath, 'tsconfig-webpack.json')
|
||||||
|
// Even though ts-loader will get the paths from webpack for module resolution
|
||||||
|
// that does not help some issues where chromium both generates ts definitions
|
||||||
|
// and has JSDoc comments for the .m.js file. Sometimes the JSDoc is incorrect
|
||||||
|
// whilst the associated .d.ts file has the correct definition. Without specifying
|
||||||
|
// the path mapping in the tsconfig.json, Typescript (via ts-loader) will use
|
||||||
|
// the JSDoc, and fail with an error. The example that prompted this is cr.sendWithPromise
|
||||||
|
// where Typescript will not see that the second parameter is an optional spread param
|
||||||
|
// and will fail with an error. Whilst this should be fixed in the chromium source,
|
||||||
|
// it's better to be explicit here so that developers get the same experience at
|
||||||
|
// both compile and design time.
|
||||||
|
const paths = {}
|
||||||
|
for (const path in pathMap) {
|
||||||
|
paths[`${path}/*`] = [`${pathMap[path]}/*`]
|
||||||
|
}
|
||||||
|
const config = {
|
||||||
|
extends: configExtendsFrom,
|
||||||
|
compilerOptions: {
|
||||||
|
paths
|
||||||
|
},
|
||||||
|
references: [
|
||||||
|
{
|
||||||
|
// This ts project is generated by //ui/webui/resources:library
|
||||||
|
path: path.join(atPath, 'ui/webui/resources/tsconfig.json')
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
await fs.writeFile(tsConfigPath, JSON.stringify(config))
|
||||||
|
return tsConfigPath
|
||||||
|
}
|
||||||
|
|
||||||
|
createGenTsConfig()
|
||||||
|
.catch(err => {
|
||||||
|
console.error(err)
|
||||||
|
process.exit(1)
|
||||||
|
})
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
// Copyright (c) 2021 The Brave Authors. All rights reserved.
|
||||||
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
|
// you can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
const path = require('path')
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
// Find files in the current build configurations /gen directory
|
||||||
|
'gen': process.env.ROOT_GEN_DIR,
|
||||||
|
// Generated resources at this path are available at chrome://resources and
|
||||||
|
// whilst webpack will still bundle, we keep the alias to the served path
|
||||||
|
// to minimize knowledge of specific gen/ paths and easily allow us to not bundle
|
||||||
|
// them in the future for certain build configurationa, just like chromium.
|
||||||
|
'chrome://resources': path.join(process.env.ROOT_GEN_DIR, 'ui/webui/resources/preprocessed'),
|
||||||
|
// We import brave-ui direct from source and not from package repo, so we need
|
||||||
|
// direct path to the src/ directory.
|
||||||
|
'brave-ui': path.resolve(__dirname, '../../node_modules/brave-ui/src'),
|
||||||
|
// Force same styled-components module for brave-core and brave-ui
|
||||||
|
// which ensure both repos code use the same singletons, e.g. ThemeContext.
|
||||||
|
'styled-components': path.resolve(__dirname, '../../node_modules/styled-components'),
|
||||||
|
}
|
||||||
@@ -4,77 +4,14 @@
|
|||||||
// you can obtain one at http://mozilla.org/MPL/2.0/.
|
// you can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
const GenerateDepfilePlugin = require('./webpack-plugin-depfile')
|
|
||||||
const fs = require('fs-extra')
|
const fs = require('fs-extra')
|
||||||
const webpack = require('webpack')
|
const webpack = require('webpack')
|
||||||
|
const GenerateDepfilePlugin = require('./webpack-plugin-depfile')
|
||||||
|
const pathMap = require('./path-map')
|
||||||
|
|
||||||
const srcPath = path.resolve(__dirname, '../../../')
|
const tsConfigPath = path.join(process.env.ROOT_GEN_DIR, 'tsconfig-webpack.json')
|
||||||
const braveSrcPath = path.join(srcPath, 'brave')
|
|
||||||
|
|
||||||
const pathMap = {
|
|
||||||
// Find files in the current build configurations /gen directory
|
|
||||||
'gen': process.env.ROOT_GEN_DIR,
|
|
||||||
// Generated resources at this path are available at chrome://resources and
|
|
||||||
// whilst webpack will still bundle, we keep the alias to the served path
|
|
||||||
// to minimize knowledge of specific gen/ paths and easily allow us to not bundle
|
|
||||||
// them in the future for certain build configurationa, just like chromium.
|
|
||||||
'chrome://resources': path.join(process.env.ROOT_GEN_DIR, 'ui/webui/resources/preprocessed'),
|
|
||||||
// We import brave-ui direct from source and not from package repo, so we need
|
|
||||||
// direct path to the src/ directory.
|
|
||||||
'brave-ui': path.resolve(__dirname, '../../node_modules/brave-ui/src'),
|
|
||||||
// Force same styled-components module for brave-core and brave-ui
|
|
||||||
// which ensure both repos code use the same singletons, e.g. ThemeContext.
|
|
||||||
'styled-components': path.resolve(__dirname, '../../node_modules/styled-components'),
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates a tsconfig.json file in the gen/ directoryc
|
|
||||||
* so that typescript can import files from cthe current build's
|
|
||||||
* gen/ directory (e.g. mojom-generated JS).
|
|
||||||
*
|
|
||||||
* @param {*} [atPath=process.env.ROOT_GEN_DIR]
|
|
||||||
* @returns void
|
|
||||||
*/
|
|
||||||
async function createGenTsConfig (atPath = process.env.ROOT_GEN_DIR) {
|
|
||||||
const configExtendsFrom = path.relative(
|
|
||||||
atPath,
|
|
||||||
path.join(braveSrcPath, 'tsconfig-webpack.json')
|
|
||||||
)
|
|
||||||
const tsConfigPath = path.join(atPath, 'tsconfig.json')
|
|
||||||
// Even though ts-loader will get the paths from webpack for module resolution
|
|
||||||
// that does not help some issues where chromium both generates ts definitions
|
|
||||||
// and has JSDoc comments for the .m.js file. Sometimes the JSDoc is incorrect
|
|
||||||
// whilst the associated .d.ts file has the correct definition. Without specifying
|
|
||||||
// the path mapping in the tsconfig.json, Typescript (via ts-loader) will use
|
|
||||||
// the JSDoc, and fail with an error. The example that prompted this is cr.sendWithPromise
|
|
||||||
// where Typescript will not see that the second parameter is an optional spread param
|
|
||||||
// and will fail with an error. Whilst this should be fixed in the chromium source,
|
|
||||||
// it's better to be explicit here so that developers get the same experience at
|
|
||||||
// both compile and design time.
|
|
||||||
const paths = {}
|
|
||||||
for (const path in pathMap) {
|
|
||||||
paths[`${path}/*`] = [`${pathMap[path]}/*`]
|
|
||||||
}
|
|
||||||
const config = {
|
|
||||||
extends: configExtendsFrom,
|
|
||||||
compilerOptions: {
|
|
||||||
paths
|
|
||||||
},
|
|
||||||
references: [
|
|
||||||
{
|
|
||||||
// This ts project is generated by //ui/webui/resources:library
|
|
||||||
path: path.join(atPath, 'ui/webui/resources/tsconfig.json')
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
await fs.writeFile(tsConfigPath, JSON.stringify(config))
|
|
||||||
return tsConfigPath
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = async function (env, argv) {
|
module.exports = async function (env, argv) {
|
||||||
// TODO(petemill): only do this once per build, in a separate target
|
|
||||||
// which the webpack targets depend on.
|
|
||||||
const tsConfigPath = await createGenTsConfig()
|
|
||||||
// Webpack config object
|
// Webpack config object
|
||||||
return {
|
return {
|
||||||
devtool: argv.mode === 'development' ? '#inline-source-map' : false,
|
devtool: argv.mode === 'development' ? '#inline-source-map' : false,
|
||||||
@@ -109,9 +46,8 @@ module.exports = async function (env, argv) {
|
|||||||
options: {
|
options: {
|
||||||
getCustomTransformers: path.join(__dirname, './webpack-ts-transformers.js'),
|
getCustomTransformers: path.join(__dirname, './webpack-ts-transformers.js'),
|
||||||
allowTsInNodeModules: true,
|
allowTsInNodeModules: true,
|
||||||
// TODO(petemill): generate in gen/ directory with baseUrl back to src/brave
|
// Use generated tsconfig so that we can point at gen/ output in the
|
||||||
// - that would remove any problems with TS analyzing types in an incorrect
|
// correct build configuration output directory.
|
||||||
// output directory (e.g. Static/ instead of Component/)
|
|
||||||
configFile: tsConfigPath
|
configFile: tsConfigPath
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -32,6 +32,7 @@
|
|||||||
"pep8": "pycodestyle --max-line-length 120 -r script",
|
"pep8": "pycodestyle --max-line-length 120 -r script",
|
||||||
"pylint": "node ./build/commands/scripts/commands.js pylint",
|
"pylint": "node ./build/commands/scripts/commands.js pylint",
|
||||||
"web-ui-gen-grd": "node components/webpack/gen-webpack-grd",
|
"web-ui-gen-grd": "node components/webpack/gen-webpack-grd",
|
||||||
|
"web-ui-gen-tsconfig": "node components/webpack/gen-tsconfig",
|
||||||
"web-ui": "webpack --config components/webpack/webpack.config.js --colors",
|
"web-ui": "webpack --config components/webpack/webpack.config.js --colors",
|
||||||
"build-storybook": "build-storybook -c .storybook -o .storybook-out",
|
"build-storybook": "build-storybook -c .storybook -o .storybook-out",
|
||||||
"storybook": "start-storybook",
|
"storybook": "start-storybook",
|
||||||
|
|||||||
Executable
+43
@@ -0,0 +1,43 @@
|
|||||||
|
import argparse
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
from lib.util import execute_stdout, scoped_cwd
|
||||||
|
|
||||||
|
|
||||||
|
NPM = 'npm'
|
||||||
|
if sys.platform in ['win32', 'cygwin']:
|
||||||
|
NPM += '.cmd'
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
args = parse_args()
|
||||||
|
root_gen_dir = args.root_gen_dir[0]
|
||||||
|
generate_tsconfig(root_gen_dir)
|
||||||
|
|
||||||
|
|
||||||
|
def parse_args():
|
||||||
|
parser = argparse.ArgumentParser(description='Generate tsconfig')
|
||||||
|
parser.add_argument('--root_gen_dir', nargs=1)
|
||||||
|
args = parser.parse_args()
|
||||||
|
# validate args
|
||||||
|
if (args.root_gen_dir is None or
|
||||||
|
len(args.root_gen_dir) != 1 or
|
||||||
|
len(args.root_gen_dir[0]) == 0):
|
||||||
|
raise Exception("root_gen_dir argument was not specified correctly")
|
||||||
|
# args are valid
|
||||||
|
return args
|
||||||
|
|
||||||
|
def generate_tsconfig(root_gen_dir, env=None):
|
||||||
|
if env is None:
|
||||||
|
env = os.environ.copy()
|
||||||
|
|
||||||
|
args = [NPM, 'run', 'web-ui-gen-tsconfig']
|
||||||
|
|
||||||
|
env["ROOT_GEN_DIR"] = root_gen_dir
|
||||||
|
|
||||||
|
dirname = os.path.abspath(os.path.join(__file__, '..', '..'))
|
||||||
|
with scoped_cwd(dirname):
|
||||||
|
execute_stdout(args, env)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
sys.exit(main())
|
||||||
Reference in New Issue
Block a user