fix(Windows): Add Windows to the Plop template (#205)

This commit is contained in:
AnastasiaOrishchenko 2020-09-03 23:10:45 +02:00 коммит произвёл Tommy Nguyen
Родитель 79e31cd4d4
Коммит d83a9712c9
5 изменённых файлов: 194 добавлений и 100 удалений

51
.github/workflows/build.yml поставляемый
Просмотреть файл

@ -327,7 +327,7 @@ jobs:
- name: Build bundle and create solution
run: |
yarn build:windows
node node_modules/react-native-test-app/windows/test-app.js
yarn install-windows-test-app
working-directory: example
- name: Install NuGet packages
run: |
@ -335,13 +335,60 @@ jobs:
working-directory: example/windows
- name: Build
run: |
MSBuild ReactTestApp.sln -t:Rebuild -p:Configuration=${{ matrix.configuration }} -p:Platform=${{ matrix.platform }}
MSBuild Example.sln -t:Rebuild -p:Configuration=${{ matrix.configuration }} -p:Platform=${{ matrix.platform }}
working-directory: example/windows
- name: Test
run: |
MSBuild ReactTestAppTests.vcxproj -t:Build -p:Configuration=${{ matrix.configuration }} -p:Platform=${{ matrix.platform }}
if ("${{ matrix.platform }}" -eq "x64") { VSTest.Console.exe ${{ matrix.platform }}\${{ matrix.configuration }}\ReactTestAppTests.dll }
working-directory: example/windows/ReactTestAppTests
windows-template:
name: "Windows [template]"
runs-on: windows-latest
strategy:
matrix:
template: [all, windows]
steps:
- name: Set up MSBuild
uses: microsoft/setup-msbuild@v1.0.1
- name: Set up Node.js
uses: actions/setup-node@v1
with:
node-version: 12
- name: Checkout
uses: actions/checkout@v2
- name: Cache /node_modules
uses: actions/cache@v2
with:
path: node_modules
key: project-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
- name: Cache /template-example/node_modules
uses: actions/cache@v2
with:
path: |
template-example/node_modules
template-example/yarn.lock
key: ${{ matrix.template }}-${{ runner.os }}-${{ hashFiles('p*e.js*') }} # package.json + plopfile.js
- name: Install
run: |
scripts/install-test-template.sh ${{ matrix.template }}
shell: bash
- name: Build bundle and create solution
run: |
yarn build:windows
if ("${{ matrix.template }}" -eq "all") { yarn install-windows-test-app }
else { yarn install-windows-test-app --projectDirectory=. }
working-directory: template-example
- name: Install NuGet packages
run: |
if ("${{ matrix.template }}" -eq "all") { cd windows }
nuget restore
working-directory: template-example
- name: Build
run: |
if ("${{ matrix.template }}" -eq "all") { MSBuild windows/TemplateExample.sln -t:Rebuild -p:Platform=x64 }
else { MSBuild TemplateExample.sln -t:Rebuild -p:Platform=x64 }
working-directory: template-example
release:
needs:
[

Просмотреть файл

@ -10,18 +10,18 @@
"@babel/highlight" "^7.10.4"
"@babel/core@^7.0.0":
version "7.11.4"
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.11.4.tgz#4301dfdfafa01eeb97f1896c5501a3f0655d4229"
integrity sha512-5deljj5HlqRXN+5oJTY7Zs37iH3z3b++KjiKtIsJy1NrjOOVSEaJHEetLBhyu0aQOSNNZ/0IuEAan9GzRuDXHg==
version "7.11.6"
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.11.6.tgz#3a9455dc7387ff1bac45770650bc13ba04a15651"
integrity sha512-Wpcv03AGnmkgm6uS6k8iwhIwTrcP0m17TL1n1sy7qD0qelDu4XNeW0dN0mHfa+Gei211yDaLoEe/VlbXQzM4Bg==
dependencies:
"@babel/code-frame" "^7.10.4"
"@babel/generator" "^7.11.4"
"@babel/generator" "^7.11.6"
"@babel/helper-module-transforms" "^7.11.0"
"@babel/helpers" "^7.10.4"
"@babel/parser" "^7.11.4"
"@babel/parser" "^7.11.5"
"@babel/template" "^7.10.4"
"@babel/traverse" "^7.11.0"
"@babel/types" "^7.11.0"
"@babel/traverse" "^7.11.5"
"@babel/types" "^7.11.5"
convert-source-map "^1.7.0"
debug "^4.1.0"
gensync "^1.0.0-beta.1"
@ -31,12 +31,12 @@
semver "^5.4.1"
source-map "^0.5.0"
"@babel/generator@^7.11.0", "@babel/generator@^7.11.4", "@babel/generator@^7.5.0":
version "7.11.4"
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.11.4.tgz#1ec7eec00defba5d6f83e50e3ee72ae2fee482be"
integrity sha512-Rn26vueFx0eOoz7iifCN2UHT6rGtnkSGWSoDRIy8jZN3B91PzeSULbswfLoOWuTuAcNwpG/mxy+uCTDnZ9Mp1g==
"@babel/generator@^7.11.5", "@babel/generator@^7.11.6", "@babel/generator@^7.5.0":
version "7.11.6"
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.11.6.tgz#b868900f81b163b4d464ea24545c61cbac4dc620"
integrity sha512-DWtQ1PV3r+cLbySoHrwn9RWEgKMBLLma4OBQloPRyDYvc5msJM9kvTLo1YnlJd1P/ZuKbdli3ijr5q3FvAF3uA==
dependencies:
"@babel/types" "^7.11.0"
"@babel/types" "^7.11.5"
jsesc "^2.5.1"
source-map "^0.5.0"
@ -248,10 +248,10 @@
chalk "^2.0.0"
js-tokens "^4.0.0"
"@babel/parser@^7.0.0", "@babel/parser@^7.10.4", "@babel/parser@^7.11.0", "@babel/parser@^7.11.4":
version "7.11.4"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.11.4.tgz#6fa1a118b8b0d80d0267b719213dc947e88cc0ca"
integrity sha512-MggwidiH+E9j5Sh8pbrX5sJvMcsqS5o+7iB42M9/k0CD63MjYbdP4nhSh7uB5wnv2/RVzTZFTxzF/kIa5mrCqA==
"@babel/parser@^7.0.0", "@babel/parser@^7.10.4", "@babel/parser@^7.11.5":
version "7.11.5"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.11.5.tgz#c7ff6303df71080ec7a4f5b8c003c58f1cf51037"
integrity sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==
"@babel/plugin-external-helpers@^7.0.0":
version "7.8.3"
@ -638,25 +638,25 @@
"@babel/parser" "^7.10.4"
"@babel/types" "^7.10.4"
"@babel/traverse@^7.0.0", "@babel/traverse@^7.10.4", "@babel/traverse@^7.11.0", "@babel/traverse@^7.8.3":
version "7.11.0"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.11.0.tgz#9b996ce1b98f53f7c3e4175115605d56ed07dd24"
integrity sha512-ZB2V+LskoWKNpMq6E5UUCrjtDUh5IOTAyIl0dTjIEoXum/iKWkoIEKIRDnUucO6f+2FzNkE0oD4RLKoPIufDtg==
"@babel/traverse@^7.0.0", "@babel/traverse@^7.10.4", "@babel/traverse@^7.11.5", "@babel/traverse@^7.8.3":
version "7.11.5"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.11.5.tgz#be777b93b518eb6d76ee2e1ea1d143daa11e61c3"
integrity sha512-EjiPXt+r7LiCZXEfRpSJd+jUMnBd4/9OUv7Nx3+0u9+eimMwJmG0Q98lw4/289JCoxSE8OolDMNZaaF/JZ69WQ==
dependencies:
"@babel/code-frame" "^7.10.4"
"@babel/generator" "^7.11.0"
"@babel/generator" "^7.11.5"
"@babel/helper-function-name" "^7.10.4"
"@babel/helper-split-export-declaration" "^7.11.0"
"@babel/parser" "^7.11.0"
"@babel/types" "^7.11.0"
"@babel/parser" "^7.11.5"
"@babel/types" "^7.11.5"
debug "^4.1.0"
globals "^11.1.0"
lodash "^4.17.19"
"@babel/types@^7.0.0", "@babel/types@^7.10.4", "@babel/types@^7.11.0", "@babel/types@^7.8.3":
version "7.11.0"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.11.0.tgz#2ae6bf1ba9ae8c3c43824e5861269871b206e90d"
integrity sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA==
"@babel/types@^7.0.0", "@babel/types@^7.10.4", "@babel/types@^7.11.0", "@babel/types@^7.11.5", "@babel/types@^7.8.3":
version "7.11.5"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.11.5.tgz#d9de577d01252d77c6800cee039ee64faf75662d"
integrity sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==
dependencies:
"@babel/helper-validator-identifier" "^7.10.4"
lodash "^4.17.19"
@ -4108,6 +4108,7 @@ react-native-test-app@../:
"@react-native-community/cli-platform-ios" "^4.5.0"
chalk "^4.1.0"
plop "^2.6.0"
yargs "^15.4.1"
react-native-windows@0.62.7:
version "0.62.7"
@ -5244,7 +5245,7 @@ yargs@^14.2.0:
y18n "^4.0.0"
yargs-parser "^15.0.1"
yargs@^15.1.0:
yargs@^15.1.0, yargs@^15.4.1:
version "15.4.1"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8"
integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==

Просмотреть файл

@ -5,6 +5,9 @@
"name": "Microsoft Open Source",
"email": "microsoftopensource@users.noreply.github.com"
},
"bin": {
"install-windows-test-app": "windows/test-app.js"
},
"repository": {
"type": "git",
"url": "https://github.com/microsoft/react-native-test-app.git"
@ -35,7 +38,8 @@
"@react-native-community/cli-platform-android": "^4.5.1",
"@react-native-community/cli-platform-ios": "^4.5.0",
"chalk": "^4.1.0",
"plop": "^2.6.0"
"plop": "^2.6.0",
"yargs": "^15.4.1"
},
"peerDependencies": {
"react": "~16.8.6 || ~16.9.0 || ~16.11.0 || ~16.13.1",

Просмотреть файл

@ -74,6 +74,9 @@ module.exports = (plop) => {
const includeMacOS =
(!exclusive || platforms === "macos") &&
isInstalled("react-native-macos", exclusive);
const includeWindows =
(!exclusive || platforms === "windows") &&
isInstalled("react-native-windows", exclusive);
const templateDir = path.dirname(
require.resolve("react-native/template/package.json")
@ -105,6 +108,7 @@ module.exports = (plop) => {
android: ["dist/res", "dist/main.android.jsbundle"],
ios: ["dist/assets", "dist/main.ios.jsbundle"],
macos: ["dist/assets", "dist/main.macos.jsbundle"],
windows: ["dist/assets", "dist/main.windows.bundle"],
},
}),
},
@ -159,7 +163,15 @@ module.exports = (plop) => {
"react-native start --config=metro.config.macos.js",
}
: undefined),
...(platforms !== "macos"
...(includeWindows
? {
"build:windows":
"mkdirp dist && react-native bundle --entry-file index.js --platform windows --dev true --bundle-output dist/main.windows.bundle --assets-dest dist --reset-cache --config=metro.config.windows.js",
"start:windows":
"react-native start --config=metro.config.windows.js",
}
: undefined),
...(platforms !== "macos" && platforms !== "windows"
? { start: "react-native start" }
: undefined),
...packageJson.scripts,
@ -169,6 +181,9 @@ module.exports = (plop) => {
...(includeMacOS
? { "react-native-macos": "0.62.1" }
: undefined),
...(includeWindows
? { "react-native-windows": "0.62.6" }
: undefined),
}),
devDependencies: sortByKeys({
...packageJson.devDependencies,
@ -335,6 +350,37 @@ module.exports = (plop) => {
}
}
if (!exclusive || platforms === "windows") {
if (isInstalled("react-native-windows", exclusive)) {
actions.push({
type: "add",
path: "metro.config.windows.js",
templateFile: require.resolve(
"react-native-windows/local-cli/generator-windows/templates/metro.config.js"
),
});
if (exclusive) {
actions.push({
type: "add",
path: "react-native.config.js",
template: [
'if (process.argv.includes("--config=metro.config.windows.js")) {',
" module.exports = {",
' reactNativePath: "node_modules/react-native-windows",',
" };",
"}",
"",
].join("\n"),
});
}
} else {
console.warn(
chalk.yellow("[WARN] ") +
"Cannot find module 'react-native-windows'; skipping Windows target"
);
}
}
return actions;
},
});

Просмотреть файл

@ -1,10 +1,23 @@
#!/usr/bin/env node
//@ts-check
const path = require("path");
const fs = require("fs");
const windowsDir = "windows";
const { argv } = require("yargs")
.usage("Usage: $0 --projectDirectory=directory")
.option("projectDirectory", {
alias: "p",
type: "string",
description: "Directory where solution will be created",
default: "windows",
});
const destPath = path.resolve(argv.projectDirectory);
const nodeModulesDir = "node_modules";
const generatedDir = ".generated";
const windowsDir = "windows";
const closestNodeModules = findClosestPathTo(nodeModulesDir);
const reactNativeModulePath = findClosestPathTo(
path.join(nodeModulesDir, "react-native-windows")
@ -12,7 +25,6 @@ const reactNativeModulePath = findClosestPathTo(
const testAppNodeModulePath = findClosestPathTo(
path.join(nodeModulesDir, "react-native-test-app")
);
const destPath = path.resolve("");
function findClosestPathTo(fileOrDirName) {
let basePath = path.resolve("");
@ -53,24 +65,11 @@ const binaryExtensions = [".png", ".pfx"];
* @param destPath Destination path.
* @param replacements: e.g. {'TextToBeReplaced': 'Replacement'}
*/
function copyAndReplace(
srcPath,
destPath,
relativeDestPath,
replacements = {}
) {
const fullDestPath = path.join(destPath, relativeDestPath);
if (fs.lstatSync(srcPath).isDirectory()) {
if (!fs.existsSync(fullDestPath)) {
fs.mkdirSync(fullDestPath);
}
return;
}
function copyAndReplace(srcPath, destPath, replacements = {}) {
const extension = path.extname(srcPath);
if (binaryExtensions.indexOf(extension) !== -1) {
// Binary file
fs.copyFile(srcPath, fullDestPath, (err) => {
fs.copyFile(srcPath, destPath, (err) => {
if (err) {
throw err;
}
@ -80,7 +79,7 @@ function copyAndReplace(
const srcPermissions = fs.statSync(srcPath).mode;
const content = resolveContents(srcPath, replacements);
fs.writeFile(
fullDestPath,
destPath,
content,
{
encoding: "utf8",
@ -115,8 +114,7 @@ function copyTestProject(
copyAndReplace(
path.join(testProjectFilePath, testProjectTemplateFile),
testProjectFilePath,
"ReactTestAppTests.vcxproj",
path.join(testProjectFilePath, "ReactTestAppTests.vcxproj"),
testProjectFileReplacements
);
}
@ -149,53 +147,62 @@ function copyProjectTemplateAndReplace(
);
fs.mkdirSync(projectFilesDestPath, { recursive: true });
fs.mkdirSync(path.join(destPath, windowsDir), { recursive: true });
fs.mkdirSync(destPath, { recursive: true });
const manifestFilePath = findClosestPathTo("app.json");
//Read path to resources from manifest
let bundleDirContent = "";
let bundleFileContent = "";
const content = fs.readFileSync(manifestFilePath);
let resourcesPaths = {};
try {
resourcesPaths = JSON.parse(content.toString()).resources;
} catch (e) {
console.warn(`Couldn't parse app.json: \n${e.message}`);
}
resourcesPaths = (resourcesPaths && resourcesPaths.windows) || resourcesPaths;
if (Array.isArray(resourcesPaths)) {
for (const resource of resourcesPaths) {
const resourceSrcPath = path.relative(
path.dirname(manifestFilePath),
resource
);
if (fs.existsSync(resourceSrcPath)) {
let relativeResourcePath = path.relative(
projectFilesDestPath,
resourceSrcPath
let appName = "ReactTestApp"; //Default value if manifest or 'name' field doesn't exist
if (manifestFilePath) {
const content = fs.readFileSync(manifestFilePath);
let resourcesPaths = {};
try {
const json = JSON.parse(content.toString());
resourcesPaths = json.resources;
appName = json.name || appName;
} catch (e) {
console.warn(`Couldn't parse \'app.json\': \n${e.message}`);
}
resourcesPaths =
(resourcesPaths && resourcesPaths.windows) || resourcesPaths;
if (Array.isArray(resourcesPaths)) {
for (const resource of resourcesPaths) {
const resourceSrcPath = path.relative(
path.dirname(manifestFilePath),
resource
);
if (fs.statSync(resourceSrcPath).isDirectory()) {
relativeResourcePath = relativeResourcePath.concat("\\**\\*");
bundleDirContent = bundleDirContent.concat(
relativeResourcePath + ";"
if (fs.existsSync(resourceSrcPath)) {
let relativeResourcePath = path.relative(
projectFilesDestPath,
resourceSrcPath
);
if (fs.statSync(resourceSrcPath).isDirectory()) {
bundleDirContent = bundleDirContent.concat(
relativeResourcePath,
"\\**\\*;"
);
} else {
bundleFileContent = bundleFileContent.concat(
relativeResourcePath,
";"
);
}
} else {
bundleFileContent = bundleFileContent.concat(
relativeResourcePath + ";"
);
console.warn(`warning: resource with path ${resource} was not found`);
}
} else {
console.warn(`warning: resource with path ${resource} was not found`);
}
}
} else {
console.warn("Could not find 'app.json' file. ");
}
const projectFilesReplacements = {
"\\$\\(ManifestRootPath\\)": path.relative(
projectFilesDestPath,
path.dirname(manifestFilePath)
),
"\\$\\(ManifestRootPath\\)": manifestFilePath
? path.relative(projectFilesDestPath, path.dirname(manifestFilePath))
: "",
"\\$\\(ReactNativeModulePath\\)": path.relative(
projectFilesDestPath,
reactNativeModulePath
@ -221,20 +228,10 @@ function copyProjectTemplateAndReplace(
}));
for (const mapping of projectFilesMappings) {
copyAndReplace(
mapping.from,
destPath,
mapping.to,
projectFilesReplacements
);
copyAndReplace(mapping.from, mapping.to, projectFilesReplacements);
}
const solutionFileDestPath = path.join(destPath, windowsDir);
const testProjectFilePath = path.join(
solutionFileDestPath,
"ReactTestAppTests"
);
const testProjectFilePath = path.join(destPath, "ReactTestAppTests");
const testProjectTemplateFile = "ReactTestAppTestsTemplate.vcxproj";
let testProjectEntry = "";
@ -257,11 +254,11 @@ function copyProjectTemplateAndReplace(
const solutionFileReplacements = {
"\\$\\(ReactNativeModulePath\\)": path.relative(
solutionFileDestPath,
destPath,
reactNativeModulePath
),
"\\$\\(ReactTestAppProjectPath\\)": path.relative(
solutionFileDestPath,
destPath,
projectFilesDestPath
),
"\\$\\(TestProject\\)": testProjectEntry,
@ -269,8 +266,7 @@ function copyProjectTemplateAndReplace(
copyAndReplace(
path.join(srcRootPath, "ReactTestApp.sln"),
destPath,
path.join(windowsDir, "ReactTestApp.sln"),
path.join(destPath, `${appName}.sln`),
solutionFileReplacements
);
}