Skip to content

Commit

Permalink
feat: add flag to force install npm dependencies to save time locally
Browse files Browse the repository at this point in the history
  • Loading branch information
shyim committed Jan 15, 2024
1 parent 1435739 commit eb74e06
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 45 deletions.
4 changes: 4 additions & 0 deletions cmd/project/project_admin_build.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,12 @@ var projectAdminBuildCmd = &cobra.Command{

sources := extension.FindAssetSourcesOfProject(cmd.Context(), projectRoot, shopCfg)

forceInstall, _ := cmd.PersistentFlags().GetBool("force-install-dependencies")

assetCfg := extension.AssetBuildConfig{
DisableStorefrontBuild: true,
ShopwareRoot: projectRoot,
NPMForceInstall: forceInstall,
}

if err := extension.BuildAssetsForExtensions(cmd.Context(), sources, assetCfg); err != nil {
Expand All @@ -52,4 +55,5 @@ var projectAdminBuildCmd = &cobra.Command{
func init() {
projectRootCmd.AddCommand(projectAdminBuildCmd)
projectAdminBuildCmd.PersistentFlags().Bool("skip-assets-install", false, "Skips the assets installation")
projectAdminBuildCmd.PersistentFlags().Bool("force-install-dependencies", false, "Force install NPM dependencies")
}
4 changes: 4 additions & 0 deletions cmd/project/project_storefront_build.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,12 @@ var projectStorefrontBuildCmd = &cobra.Command{

sources := extension.FindAssetSourcesOfProject(cmd.Context(), projectRoot, shopCfg)

forceInstall, _ := cmd.PersistentFlags().GetBool("force-install-dependencies")

assetCfg := extension.AssetBuildConfig{
DisableAdminBuild: true,
ShopwareRoot: projectRoot,
NPMForceInstall: forceInstall,
}

if err := extension.BuildAssetsForExtensions(cmd.Context(), sources, assetCfg); err != nil {
Expand All @@ -52,4 +55,5 @@ var projectStorefrontBuildCmd = &cobra.Command{
func init() {
projectRootCmd.AddCommand(projectStorefrontBuildCmd)
projectStorefrontBuildCmd.PersistentFlags().Bool("skip-theme-compile", false, "Skip theme compilation")
projectStorefrontBuildCmd.PersistentFlags().Bool("force-install-dependencies", false, "Force install NPM dependencies")
}
106 changes: 61 additions & 45 deletions extension/asset_platform.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"os"
"os/exec"
"path"
"path/filepath"
"strings"

"github.com/FriendsOfShopware/shopware-cli/internal/asset"
Expand All @@ -34,6 +33,7 @@ type AssetBuildConfig struct {
ShopwareVersion *version.Constraints
Browserslist string
SkipExtensionsWithBuildFiles bool
NPMForceInstall bool
}

func BuildAssetsForExtensions(ctx context.Context, sources []asset.Source, assetConfig AssetBuildConfig) error { // nolint:gocyclo
Expand Down Expand Up @@ -62,7 +62,7 @@ func BuildAssetsForExtensions(ctx context.Context, sources []asset.Source, asset
defer deletePaths(ctx, shopwareRoot)
}

paths, err := InstallNodeModulesOfConfigs(ctx, cfgs, true)
paths, err := InstallNodeModulesOfConfigs(ctx, cfgs, assetConfig.NPMForceInstall)
if err != nil {
return err
}
Expand All @@ -89,20 +89,22 @@ func BuildAssetsForExtensions(ctx context.Context, sources []asset.Source, asset

administrationRoot := PlatformPath(shopwareRoot, "Administration", "Resources/app/administration")

var additionalNpmParameters []string
if assetConfig.NPMForceInstall || !nodeModulesExists(administrationRoot) {
var additionalNpmParameters []string

npmPackage, err := getNpmPackage(administrationRoot)
npmPackage, err := getNpmPackage(administrationRoot)

if err != nil {
return err
}
if err != nil {
return err
}

if doesPackageJsonContainsPackageInDev(npmPackage, "puppeteer") {
additionalNpmParameters = []string{"--production"}
}
if doesPackageJsonContainsPackageInDev(npmPackage, "puppeteer") {
additionalNpmParameters = []string{"--production"}
}

if err := installDependencies(administrationRoot, npmPackage, additionalNpmParameters...); err != nil {
return err
if err := installDependencies(administrationRoot, npmPackage, additionalNpmParameters...); err != nil {
return err
}
}

err = npmRunBuild(
Expand Down Expand Up @@ -166,33 +168,35 @@ func BuildAssetsForExtensions(ctx context.Context, sources []asset.Source, asset

storefrontRoot := PlatformPath(shopwareRoot, "Storefront", "Resources/app/storefront")

envList := []string{
fmt.Sprintf("PROJECT_ROOT=%s", shopwareRoot),
fmt.Sprintf("STOREFRONT_ROOT=%s", storefrontRoot),
}
if assetConfig.NPMForceInstall || !nodeModulesExists(storefrontRoot) {
if err := patchPackageLockToRemoveCanIUsePackage(path.Join(storefrontRoot, "package-lock.json")); err != nil {
return err
}

if err := patchPackageLockToRemoveCanIUsePackage(path.Join(storefrontRoot, "package-lock.json")); err != nil {
return err
}
additionalNpmParameters := []string{"caniuse-lite"}

if assetConfig.Browserslist != "" {
envList = append(envList, fmt.Sprintf("BROWSERSLIST=%s", assetConfig.Browserslist))
}
npmPackage, err := getNpmPackage(storefrontRoot)

additionalNpmParameters := []string{"caniuse-lite"}
if err != nil {
return err
}

npmPackage, err := getNpmPackage(storefrontRoot)
if doesPackageJsonContainsPackageInDev(npmPackage, "puppeteer") {
additionalNpmParameters = append(additionalNpmParameters, "--production")
}

if err != nil {
return err
if err := installDependencies(storefrontRoot, npmPackage, additionalNpmParameters...); err != nil {
return err
}
}

if doesPackageJsonContainsPackageInDev(npmPackage, "puppeteer") {
additionalNpmParameters = append(additionalNpmParameters, "--production")
envList := []string{
fmt.Sprintf("PROJECT_ROOT=%s", shopwareRoot),
fmt.Sprintf("STOREFRONT_ROOT=%s", storefrontRoot),
}

if err := installDependencies(storefrontRoot, npmPackage, additionalNpmParameters...); err != nil {
return err
if assetConfig.Browserslist != "" {
envList = append(envList, fmt.Sprintf("BROWSERSLIST=%s", assetConfig.Browserslist))
}

err = npmRunBuild(
Expand All @@ -214,23 +218,31 @@ func BuildAssetsForExtensions(ctx context.Context, sources []asset.Source, asset
return nil
}

func nodeModulesExists(root string) bool {
if _, err := os.Stat(path.Join(root, "node_modules")); err == nil {
return true
}

return false
}

func InstallNodeModulesOfConfigs(ctx context.Context, cfgs ExtensionAssetConfig, force bool) ([]string, error) {
paths := make([]string, 0)

// Install shared node_modules between admin and storefront
for _, entry := range cfgs {
possibleNodePaths := []string{
// shared between admin and storefront
filepath.Join(entry.BasePath, "Resources", "app", "package.json"),
path.Join(entry.BasePath, "Resources", "app", "package.json"),
}

// only try administration and storefront node_modules folder when we have an entry file
if entry.Administration.EntryFilePath != nil {
possibleNodePaths = append(possibleNodePaths, filepath.Join(entry.BasePath, "Resources", "app", "administration", "package.json"), filepath.Join(entry.BasePath, "Resources", "app", "administration", "src", "package.json"))
possibleNodePaths = append(possibleNodePaths, path.Join(entry.BasePath, "Resources", "app", "administration", "package.json"), path.Join(entry.BasePath, "Resources", "app", "administration", "src", "package.json"))
}

if entry.Storefront.EntryFilePath != nil {
possibleNodePaths = append(possibleNodePaths, filepath.Join(entry.BasePath, "Resources", "app", "storefront", "package.json"), filepath.Join(entry.BasePath, "Resources", "app", "storefront", "src", "package.json"))
possibleNodePaths = append(possibleNodePaths, path.Join(entry.BasePath, "Resources", "app", "storefront", "package.json"), path.Join(entry.BasePath, "Resources", "app", "storefront", "src", "package.json"))
}

additionalNpmParameters := []string{}
Expand All @@ -241,13 +253,9 @@ func InstallNodeModulesOfConfigs(ctx context.Context, cfgs ExtensionAssetConfig,

for _, possibleNodePath := range possibleNodePaths {
if _, err := os.Stat(possibleNodePath); err == nil {
npmPath := filepath.Dir(possibleNodePath)

if !entry.NpmStrict {
logging.FromContext(ctx).Infof("Please consider enabling npm_strict for %s to speed up the build process in the .shopware-extension.yml of the extension. See https://sw-cli.fos.gg/shopware-extension-yml-schema/", entry.TechnicalName)
}
npmPath := path.Dir(possibleNodePath)

if _, err := os.Stat(filepath.Join(npmPath, "node_modules")); err == nil && !force {
if !force && nodeModulesExists(npmPath) {
continue
}

Expand All @@ -257,6 +265,14 @@ func InstallNodeModulesOfConfigs(ctx context.Context, cfgs ExtensionAssetConfig,
return nil, err
}

additionalText := ""

if !entry.NpmStrict {
additionalText = " (consider enabling npm_strict mode, to install only production relevant dependencies)"
}

logging.FromContext(ctx).Infof("Installing npm dependencies in %s %s\n", npmPath, additionalText)

if err := installDependencies(npmPath, npmPackage, additionalNpmParameters...); err != nil {
return nil, err
}
Expand Down Expand Up @@ -292,17 +308,17 @@ func npmRunBuild(path string, buildCmd string, buildEnvVariables []string) error
return nil
}

func getInstallCommand(path string, isProductionMode bool, npmPackage npmPackage) *exec.Cmd {
if _, err := os.Stat(filepath.Join(path, "pnpm-lock.yaml")); err == nil {
func getInstallCommand(root string, isProductionMode bool, npmPackage npmPackage) *exec.Cmd {
if _, err := os.Stat(path.Join(root, "pnpm-lock.yaml")); err == nil {
return exec.Command("pnpm", "install")
}

if _, err := os.Stat(filepath.Join(path, "yarn.lock")); err == nil {
if _, err := os.Stat(path.Join(root, "yarn.lock")); err == nil {
return exec.Command("yarn", "install")
}

// @see https://github.com/oven-sh/bun/issues/7755
if _, err := os.Stat(filepath.Join(path, "bun.lockdb")); err == nil && !isProductionMode {
if _, err := os.Stat(path.Join(root, "bun.lockdb")); err == nil && !isProductionMode {
return exec.Command("bun", "install")
}

Expand Down Expand Up @@ -342,8 +358,8 @@ func installDependencies(path string, packageJsonData npmPackage, additionalPara
return nil
}

func getNpmPackage(path string) (npmPackage, error) {
packageJsonFile, err := os.ReadFile(filepath.Join(path, "package.json"))
func getNpmPackage(root string) (npmPackage, error) {
packageJsonFile, err := os.ReadFile(path.Join(root, "package.json"))
if err != nil {
return npmPackage{}, err
}
Expand Down
2 changes: 2 additions & 0 deletions wiki/docs/commands/project.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ Builds the Administration with all installed extensions
Parameters:

* `--skip-assets-install` - Skips the assets installation
* `--force-install-dependencies` - Forces the installation of NPM dependencies

## shopware-cli project storefront-build

Expand All @@ -27,6 +28,7 @@ Builds the Storefront with all installed extensions
Parameters:

* `--skip-theme-compile` - Skips the theme compilation
* `--force-install-dependencies` - Forces the installation of NPM dependencies

## shopware-cli project worker

Expand Down

0 comments on commit eb74e06

Please sign in to comment.