angular / angular-cli

CLI tool for Angular
https://cli.angular.io
MIT License
26.73k stars 11.98k forks source link

Angular (+ CLI) 6.0.0: Global styles for libraries #10869

Closed jhuenges closed 5 years ago

jhuenges commented 6 years ago

Versions

Angular CLI: 6.0.1
Node: 8.9.4
OS: win32 x64
Angular:
...

Package                      Version
------------------------------------------------------
@angular-devkit/architect    0.6.1
@angular-devkit/core         0.6.1
@angular-devkit/schematics   0.6.1
@schematics/angular          0.6.1
@schematics/update           0.6.1
rxjs                         6.1.0
typescript                   2.7.2

Repro steps

Observed behavior

The global styles from the library are not copied/used

Desired behavior

Global styles inside a library should be part of the generated output. I know that I could use component level styles (this works). However this doesnt work in all use cases. For example I have some css to style buttons but I dont have a ButtonComponent (and I dont want one) since I am only modifying the html <button> tag with the css and I am not adding some behaviour.

Mention any other details that might be useful (optional)

kroeder commented 6 years ago

I tried to add styles: [] in my angular.json but get a

Schema validation failed with the following errors:
  Data path "" should NOT have additional properties(styles).

https://github.com/angular/angular-cli/wiki/stories-global-styles shows, how to use global styles. This does not work when you add them into your library json configuration

  "my-library": {
      [...]
      "architect": {
        "build": {
          "builder": "@angular-devkit/build-ng-packagr:build",
          "options": {
            [...]
            "styles": [
              "styles/styles.scss"
            ]
  [...]

The documentation feels misleading since this does work for app builds but not for libraries. Or am I doing something wrong?

clydin commented 6 years ago

The options are particular to the referenced builder (in this case, "builder": "@angular-devkit/build-ng-packagr:build",). Both it and ng-packagr would need to add support to allow for such an option.

kroeder commented 6 years ago

Okay - I've used ng-packgr before. Afaik there's no support for global css in ng-packagr and I had to add own build steps in order to get this running

Since having a global css file seems to me like a common thing, is there any plan to collab with the ng-packagr project on this?

jhuenges commented 6 years ago

Any update on this?

kroeder commented 6 years ago

@jhuenges if it helps, here's a gulp task snippet as workaround (or long-term solution, depending on what the angular team is planning 😃 )

The snippet includes:

const gulp = require('gulp');
const sass = require('gulp-sass');
const concat = require('gulp-concat');
const run = require('gulp-run');

const projectName = 'your-library';
const distDir = './dist/' + projectName;

gulp.task('build:angular-package', function () {
    return run('ng build ' + projectName + ' --prod', {}).exec();
});

gulp.task('build:sass', ['build:angular-package'], function () {
    return gulp.src(['./src/lib/styles/styles.scss', './src/assets/**/*.scss'])
        .pipe(sass().on('error', sass.logError))
        .pipe(concat('styles.css'))
        .pipe(gulp.dest(distDir));
});

gulp.task('build:copy-assets', ['build:angular-package'], function () {
    return gulp.src(['src/assets/fonts/icons8/*', 'src/assets/fonts/opensans/v15/*'])
        .pipe(gulp.dest(distDir));
});

gulp.task('build', [
    'build:angular-package',
    'build:sass',
    'build:copy-assets'
]);

I had to change a couple of things since we have a slightly different custom-build but it should give an idea on how you can solve this.

Of course you need to install the necessary gulp-packages.

jhuenges commented 6 years ago

Thanks! I will try to use this, but an official solution would be great :)

cm0s commented 6 years ago

Here is another solution using only node package. In your package.json add dependency to package cpx and scss-bundle. Then add the following entries in your package.json "scripts" property :

"scripts": {
...
"build-mylib": "ng build mylib && npm run build-mylib-styles && npm run cp-mylib-assets",
"build-mylib-styles": "cpx \"./projects/mylib/src/lib/style/**/*\" \"./dist/mylib/style\" && scss-bundle -e ./projects/mylib/src/lib/style/_style.scss -d ./dist/mylib/style/_styles.scss",
"cp-mylib-assets": "cpx \"./src/assets/**/*\" \"./dist/mylib/assets\"",
}

The build-mylib-styles works in two steps. First it copys all styles files found in the lib/style folder and then it uses the scss-bundle package to bundle all imports of the _style.scss file. I have other files in the lib/style folder without import so no need to bundle them.

gus-canya commented 6 years ago

Hi. I wrote another solution that adapts to the projects/** directory structure for multiple library projects:

./projects
  my-lib/
    src/ 
      lib/
        my-lib-component/
           my-lib.component.css
./src
  assets/
    sass/
      projects/
       my-lib/
         my-lib-component/
           my-lib.component.scss

gulpfile.js:

let gulp = require('gulp');
let sass = require('gulp-sass');
let autoprefixer = require('gulp-autoprefixer');
const aliases = require('gulp-style-aliases');

let fs                = require('fs');
let path              = require('path');
let cssTaskDictionary = [];
let cssTaskList       = [];
let watchTaskList     = [];

// SRC PATH definitions
let publicFolder = './projects';
let srcFolder = './src/assets';

let cssSrcPath = `${srcFolder}/sass/projects`;
let cssDest    = `${publicFolder}`;

// Gather Scss src files to watch and compile
(fs.readdirSync(cssSrcPath) || []).filter(directory => {
  let isDirectory = fs.lstatSync(path.join(cssSrcPath, directory)).isDirectory();
  return  !/global/.test(directory) &&
          !/theme/.test(directory) &&
          isDirectory;
}).forEach(project => {
  (fs.readdirSync(path.join(cssSrcPath, project)) || []).filter(projectCtrl => {
    return fs.lstatSync(path.join(cssSrcPath, project, projectCtrl)).isDirectory();
  }).forEach(directory => {
    fs.readdirSync(path.join(cssSrcPath, project, directory)).forEach(file => {
      cssTaskDictionary.push({ project: project, directory: directory, file: file });
    });
  });
});

cssTaskDictionary.forEach(taskDef => {

  let file = taskDef.file.replace(/\.scss/, '');
  file = file.replace(/_/, '');
  let taskSuffix = '-' + taskDef.project + '-' + taskDef.directory + '-' + file;
  let taskName = 'css' + taskSuffix;
  cssTaskList.push(taskName);

  // Sass will watch for changes in this file
  let srcPathFile = path.join(cssSrcPath, taskDef.project, taskDef.directory, taskDef.file);

  let destination = path.join(cssDest, taskDef.project, '/src/lib', taskDef.directory);

  gulp.task(taskName, () => {
    gulp.src([srcPathFile])
      .pipe(aliases({
        '@bootstrap': 'node_modules/bootstrap/scss',
        '@ebm': 'node_modules/ebm',
        '@sass': 'src/assets/sass',
        }))
      .pipe(sass({
        outputStyle: 'compressed'
      }).on('error', sass.logError))
      .pipe(autoprefixer({
        browsers: ['last 2 versions'],
        cascade: false,
        flexbox: true,
        }))
      .pipe(gulp.dest(destination)
    );
  });

  // Instantiate directory specific watch tasks
  let watchTaskName = 'watch-' + taskName;
  watchTaskList.push(watchTaskName);
  gulp.task(watchTaskName, () => {
    gulp.watch([srcPathFile], [taskName]);
  });
});

gulp.task('watch', watchTaskList);
h-arora commented 6 years ago

This might be a good read when a official solution is not yet ready: https://medium.com/@Dor3nz/compiling-css-in-new-angular-6-libraries-26f80274d8e5

ramandeep-singh-1983 commented 5 years ago

Here is another solution using only node package. In your package.json add dependency to package cpx and scss-bundle. Then add the following entries in your package.json "scripts" property :

"scripts": {
...
"build-mylib": "ng build mylib && npm run build-mylib-styles && npm run build-mylib-assets",
"build-mylib-styles": "cpx \"./projects/mylib/src/lib/style/**/*\" \"./dist/mylib/style\" && scss-bundle -e ./projects/mylib/src/lib/style/_style.scss -d ./dist/mylib/style/_styles.scss",
"build-mylib-assets": "cpx \"./src/assets/**/*\" \"./dist/mylib/assets\"",
}

The build-mylib-styles works in two steps. First it copys all styles files found in the lib/style folder and then it uses the scss-bundle package to bundle all imports of the _style.scss file. I have other files in the lib/style folder without import so no need to bundle them.

Thanks! this solution works well. However, the new watch mode for the library doesn't work after this. So, one needs to rebuild and serve the page manually after any code change. Any way to make the watch mode work with this?

amirofy2002 commented 5 years ago

but while packaging angular try to remove the script section of package.json and the following message occurs:

Removing scripts section in package.json as it's considered a potential security vulnerability.

jhuenges commented 5 years ago

Why would you do that?!

FirstVertex commented 5 years ago

@ramandeep-singh-1983 i got it to work with watch mode, for everything except the scss-bundle, which i guess has to be a post-build step.

i used concurrently and rimraf, in addition to the already mentioned cpx and scss-bundle

here's the scripts i developed for it:

  "scripts": {
    "clean": "rimraf \"./dist/*\"",
    "scss-bundle": "scss-bundle -e \"./framework/src/styles/_framework.scss\" -d \"./dist/framework/styles/_framework.scss\"",
    "watch-ts": "ng build --watch=true",
    "watch-scss": "cpx \"./framework/src/styles/**/*\" \"./dist/framework/styles\" --watch --verbose",    
    "watch-assets": "cpx \"./framework/src/assets/**/*\" \"./dist/framework/assets\"  --watch --verbose",
    "watchAll": "npm run clean & concurrently \"npm:watch-*\""
  },

i put in the clean step because i have configured my ng-package.json with "deleteDestPath": false this allows me to control the deleting of the output folder myself. that way ng build --watch doesn't keep wiping out the work done by cpx every time a .ts file changes

i opened an issue in scss-bundle repo to ask them about adding a -watch mode https://github.com/SimplrJS/scss-bundle/issues/57

mattiLeBlanc commented 5 years ago

Would love to know when there is a general solution. For now I am just creating a core-component which loads in the styles which I have to reference once above my app-root. Not as nice, but works for now. You might have to add the core-component to the bootstrap next to you app-root for it to work. Otherwise load it once in your app-component.

cm0s commented 5 years ago

[...]

i opened an issue in scss-bundle repo to ask them about adding a -watch mode SimplrJS/scss-bundle#57

Thanks to @hughanderson4 there is now a watch mode for scss-bundle (see version 2.5.0-beta)

cm0s commented 5 years ago

@ramandeep-singh-1983 i got it to work with watch mode, for everything except the scss-bundle, which i guess has to be a post-build step.

i used concurrently and rimraf, in addition to the already mentioned cpx and scss-bundle

here's the scripts i developed for it:

  "scripts": {
    "clean": "rimraf \"./dist/*\"",
    "scss-bundle": "scss-bundle -e \"./framework/src/styles/_framework.scss\" -d \"./dist/framework/styles/_framework.scss\"",
    "watch-ts": "ng build --watch=true",
    "watch-scss": "cpx \"./framework/src/styles/**/*\" \"./dist/framework/styles\" --watch --verbose",    
    "watch-assets": "cpx \"./framework/src/assets/**/*\" \"./dist/framework/assets\"  --watch --verbose",
    "watchAll": "npm run clean & concurrently \"npm:watch-*\""
  },

i put in the clean step because i have configured my ng-package.json with "deleteDestPath": false this allows me to control the deleting of the output folder myself. that way ng build --watch doesn't keep wiping out the work done by cpx every time a .ts file changes

i opened an issue in scss-bundle repo to ask them about adding a -watch mode SimplrJS/scss-bundle#57

@hughanderson4 your solution is great, but I encountered a problem while using it. The ng build --watch command automatically clean the dist folder. When running the assets/css/bundle scripts in parallel with the ng build, the cpx and scss-bundle commands are executed before the ng build dist cleaning resulting in the deletation of the newly copied files.

To overcome this situation :

FirstVertex commented 5 years ago

Yeah buddy similarly in my lib I got a ng-package.json and I had to modify like this to prevent the cleaning of the output folder:

{
  ...
  "deleteDestPath": false,
  ...
}

That why I manually put in the rimraf step. Since ng build not doing that for me anymore.

I had problems trying to run all of it concurrently. My workflow is to start the watch-ts and then after it has done the initial build then I start the watch-assets and watch-scss commands (if needed for that dev session), which is working pretty well for me.

cm0s commented 5 years ago

Great, thanks for sharing this solution. I didn't think about directly checking ng-packagr config options. Now I understand why you were using rimraf. It makes more sense ;).

I'm able to run the watchers together and everything seems to work fine. I use npm-run-all to run parallel watch tasks, but it probably works the same way concurrently works (I didn't take the time to check).

FirstVertex commented 5 years ago

Great job, yeah npm-run-all is about the same as concurrently, I selected concurrently since it has wild card support to run bunch of jobs at same time. ✌️

ramandeep-singh-1983 commented 5 years ago

Thanks @hughanderson4, the watch mode is working nicely for me now with the following code:

"scripts": { "clean": "rimraf \"./dist/*\"", "scss-bundle": "scss-bundle -e \"./projects/my-lib/src/lib/shared/styles/styles.scss\" -d \"./dist/my-lib/styles/styles.scss\"", "watch-ts": "ng build --watch=true", "watch-scss": "cpx \"./projects/my-lib/src/lib/shared/styles/*/\" \"./dist/my-lib/styles\" --watch --verbose && scss-bundle",
"watch-assets": "cpx \"./my-lib/src/assets/*/\" \"./dist/my-lib/assets\" --watch --verbose", "watchAll": "npm run clean & concurrently \"npm:watch-*\"" },

I have added " && scss-bundle" in the "watch-scss" command as "scss-bundle" was not being called anywhere in the code you posted.

However, i have 1 issue: The dist folder has 2 sub-directories: app, my-lib

the assets and styles are copied inside the my-lib directory after running "npm run watchAll". Now, how do i use the dist/my-lib\styles/_styles.scss in my application? I have made the application's styles.scss empty as i want all library specific global styles to go under my-lib/styles/_style.scss

FirstVertex commented 5 years ago

Hi @ramandeep-singh-1983

"scss-bundle" was not being called

Yeah I was launching that separately back then. Now, here is my latest package.json commands which work really nice. I need to run only the watch command and it does everything:

  "scripts": {
    "clean": "rimraf \"./dist/*\"",
    "watch": "npm run clean && concurrently \"ng build --watch=true\" \"npm:watch-scss-*\" \"npm:watch-assets\"",
    "watch-scss-framework": "scss-bundle -e \"./framework/styles/_framework.scss\" -d \"./dist/framework/styles/_framework.scss\" -w \"./framework/styles\"",
    "watch-scss-variables": "scss-bundle -e \"./framework/styles/variables.scss\" -d \"./dist/framework/styles/variables.scss\" -w \"./framework/styles\"",
    "watch-assets": "cpx \"./framework/assets/**/*\" \"./dist/framework/assets\" --watch --verbose"
  }

I bundled my variables.scss file separately so users of my framework could refer to them without importing entire framework.scss.

To answer your question, good sir, in your app (not lib) go to the angular.json and add this under projects\MyAwesomeApp\architect\build\options:

            "stylePreprocessorOptions": {
              "includePaths": [
                "/dist/my-lib/styles/"
              ]
            },

Ater that, in your app in any .scss file you should be able to write @import "styles"; to bring in your lib's _styles.scss.

ramandeep-singh-1983 commented 5 years ago

Thanks! it worked. I also referred this article about global styles: https://scotch.io/tutorials/angular-shortcut-to-importing-styles-files-in-components

ramandeep-singh-1983 commented 5 years ago

Another question: My global style is being picked up from the library scss file now but what about the assets directory. Right now, the dist directory has this structure:

my-app

app js files assets my-lib:

assets styles Suppose my library is a full fledged GUI library. The global styles reside in my library and are picked up by the app using @import statement. But what about the assets directory (icons, fonts etc.). They are part of my library but i have to copy them over to the my-app/assets directory for it to work. The my-lib directory resides outside the my-app directory in the dist directory so is it possible to pick up assets from the my-lib directory?

The my-app should be independent of my-lib so ideally it shouldn't need to contain assets for my-lib and all assets belonging to my-lib should be part of my-lib directory only.

FirstVertex commented 5 years ago

@ramandeep-singh-1983 My watch-assets command is just a cpx that gonna copy my assets from my lib project to my lib project's dist\assets folder.

Then I have to config each of my client apps to do this glob:

            "assets": [
              "src/favicon.png",
              "src/assets",
              {
                "glob": "**/*",
                "input": "node_modules/@dynatron/framework/assets/",
                "output": "./assets/framework"
              }
            ]

This goes in the angular.json under projects\MyAwesomeApp\architect\build\options This glob gonna copy all my framework assets into my client site's assets/framework folder where they can be used. That way my framework could provide multimedia assets to be used by all clients.

Hope it helps bro! 🍺

mgechev commented 5 years ago

Excellent discussion here! I can already see a few workarounds which seem reasonable. Although I'd discourage global styles in libraries, if your use case require such I'd recommend you to look at ngx-build-plus. You can customize your build using it.

Closing the issue here. If you think we're missing something and it's essential for the CLI to support this out of the box (i.e., you have use cases that we have thought about), please open a new issue.

ramandeep-singh-1983 commented 5 years ago

Thanks @hughanderson4 for your help, the assets thing worked too :) @mgechev, thanks for the info about ngx-build-plus, i will explore it.

About the need to bundle global style in libraries: I am creating a UI application as a library and don't want to be dependent on the base app for the styles or assets, so my requirement is to have everything inside the library itself.

vinagreti commented 5 years ago

Hey guys.

The best solution IMHO is using cpx in the package.json to copy the css files and use npm run build.lib when building your library:

"scripts": {
...
  "build.lib": "ng build my-lib && npm run copy-styles",
  "copy-styles": "cpx \"./projects/my-lib/src/lib/assets/styles/**/*.scss\" \"./dist/my-lib/assets/styles/\"",
...
}

In your main application configure the tsconfig PATHS for pointing to your lib directory and than use your lib as you do with installed ones.

tsconfig.json

{
  ...
  "compilerOptions": {
   ...
    "paths": {
      "my-lib": [
        "projects/my-lib"
      ],
     ...
    }
  }
}

my-component.scss

@import '~my-lib/assets/my-style';

When the cli notice the ~ in the import it will try to load from the configured path and if nothing is found it will look inside node_modules so you can use the local lib or the installed one without caring about changing the imports. It is like simulating an installation of the lib.

With this approach you can use paths everywhere to access different places in your cli app.

ermarkar commented 5 years ago

Hi @ramandeep-singh-1983

"scss-bundle" was not being called

Yeah I was launching that separately back then. Now, here is my latest package.json commands which work really nice. I need to run only the watch command and it does everything:

  "scripts": {
    "clean": "rimraf \"./dist/*\"",
    "watch": "npm run clean && concurrently \"ng build --watch=true\" \"npm:watch-scss-*\" \"npm:watch-assets\"",
    "watch-scss-framework": "scss-bundle -e \"./framework/styles/_framework.scss\" -d \"./dist/framework/styles/_framework.scss\" -w \"./framework/styles\"",
    "watch-scss-variables": "scss-bundle -e \"./framework/styles/variables.scss\" -d \"./dist/framework/styles/variables.scss\" -w \"./framework/styles\"",
    "watch-assets": "cpx \"./framework/assets/**/*\" \"./dist/framework/assets\" --watch --verbose"
  }

I bundled my variables.scss file separately so users of my framework could refer to them without importing entire framework.scss.

To answer your question, good sir, in your app (not lib) go to the angular.json and add this under projects\MyAwesomeApp\architect\build\options:

            "stylePreprocessorOptions": {
              "includePaths": [
                "/dist/my-lib/styles/"
              ]
            },

Ater that, in your app in any .scss file you should be able to write @import "styles"; to bring in your lib's _styles.scss.

Hi thanks for your build scripts,

1) but I am still not able to run scss-bundle in watch mode this is how I am using

"watch-scss": "scss-bundle -e \"./projects/my-lib/src/lib/sass/my-lib.scss\" -d \"./dist-lib/my-lib/sass/my-lib.scss\" -w \"./projects/my-lib/src/lib/sass\""

2) I want to run both my application project and my library in watch mode so that if there is any change it should re-compiled automatically and these are the scripts I am using

"scripts": {
     "start": "yarn clean && ng build my-lib && concurrently \"ng serve\" \"ng build qwc --watch=true\" \"yarn:watch-scss\"",
    "clean": "rimraf \"./dist-lib/*\"",
    "watch-scss": "scss-bundle -e \"./projects/my-lib/src/lib/sass/my-lib.scss\" -d \"./dist-lib/my-lib/sass/my-lib.scss\" -w \"./projects/my-lib/src/lib/sass\""
}

but this fails by saying

ERROR in src/app/app.module.ts(23,27): error TS2307: Cannot find module 'my-lib'.

can you please help?

ramandeep-singh-1983 commented 5 years ago

Hi @ramandeep-singh-1983

"scss-bundle" was not being called

Yeah I was launching that separately back then. Now, here is my latest package.json commands which work really nice. I need to run only the watch command and it does everything:

  "scripts": {
    "clean": "rimraf \"./dist/*\"",
    "watch": "npm run clean && concurrently \"ng build --watch=true\" \"npm:watch-scss-*\" \"npm:watch-assets\"",
    "watch-scss-framework": "scss-bundle -e \"./framework/styles/_framework.scss\" -d \"./dist/framework/styles/_framework.scss\" -w \"./framework/styles\"",
    "watch-scss-variables": "scss-bundle -e \"./framework/styles/variables.scss\" -d \"./dist/framework/styles/variables.scss\" -w \"./framework/styles\"",
    "watch-assets": "cpx \"./framework/assets/**/*\" \"./dist/framework/assets\" --watch --verbose"
  }

I bundled my variables.scss file separately so users of my framework could refer to them without importing entire framework.scss. To answer your question, good sir, in your app (not lib) go to the angular.json and add this under projects\MyAwesomeApp\architect\build\options:

            "stylePreprocessorOptions": {
              "includePaths": [
                "/dist/my-lib/styles/"
              ]
            },

Ater that, in your app in any .scss file you should be able to write @import "styles"; to bring in your lib's _styles.scss.

Hi thanks for your build scripts,

  1. but I am still not able to run scss-bundle in watch mode this is how I am using

"watch-scss": "scss-bundle -e \"./projects/my-lib/src/lib/sass/my-lib.scss\" -d \"./dist-lib/my-lib/sass/my-lib.scss\" -w \"./projects/my-lib/src/lib/sass\""

  1. I want to run both my application project and my library in watch mode so that if there is any change it should re-compiled automatically and these are the scripts I am using
"scripts": {
     "start": "yarn clean && ng build my-lib && concurrently \"ng serve\" \"ng build qwc --watch=true\" \"yarn:watch-scss\"",
    "clean": "rimraf \"./dist-lib/*\"",
    "watch-scss": "scss-bundle -e \"./projects/my-lib/src/lib/sass/my-lib.scss\" -d \"./dist-lib/my-lib/sass/my-lib.scss\" -w \"./projects/my-lib/src/lib/sass\""
}

but this fails by saying

ERROR in src/app/app.module.ts(23,27): error TS2307: Cannot find module 'my-lib'.

can you please help?

The following set works for me:

"clean": "rimraf \"./dist/*\"", "watch-scss": "scss-bundle -e \"./projects/my-lib/src/styles/_my-lib.scss\" -d \"./dist/my-lib/styles/_my-lib.scss\" -w \"./projects/my-lib/src/styles\"", "watch-assets": "cpx \"./projects/my-lib/src/assets/*/\" \"./dist/my-lib/assets\" --watch --verbose", "watch": "npm run clean && concurrently \"ng build --watch=true\" \"npm:watch-scss\" \"npm:watch-assets\"",

I use 2 terminals, in one i use "npm run watch" and in the other i run "ng serve" and whenever i make any changes to my library's code, both build up pretty fast and the Angular app is automatically updated.

ermarkar commented 5 years ago

@ramandeep-singh-1983 Thanks for your answer.

1) But isn't ng build --watch=true will build the app itself rather than the library.

2) And My library is dependent on materialize-css and I need to import its scss files into lib's global scss, but this is not working until I installed the materialize-css to my application project. Is this the only way?

3) As I am using the scss-bundle and this will bundle all the scss files into one but there is an scss files that imports some resources like

@font-face { font-family:"Roboto Regular"; font-weight:normal; font-style:normal; src: url("../../resources/fonts/roboto-regular/Roboto-Regular.eot?") format("eot"), / IE9 Compat Modes / url("../../resources/fonts/roboto-regular/Roboto-Regular.woff") format("woff"), / Pretty Modern Browsers / url("../../resources/fonts/roboto-regular/Roboto-Regular.ttf") format("truetype"); / Safari, Android, iOS / / url("../../resources/fonts/roboto-regular/Roboto-Regular.svg#Roboto-Regular") format("svg"); / / Legacy iOS / }

and I copied the resources folder as well but as there is only one bundled scss file for all scss (no folder hierarchy) so ../../resources fails as there need only one ../resources, what is the proposed solution ?

ramandeep-singh-1983 commented 5 years ago

@ramandeep-singh-1983 Thanks for your answer.

  1. But isn't ng build --watch=true will build the app itself rather than the library. As i mentioned, i run 2 commands in parallel, 'npm run watch' watches and rebuilds the library and 'ng serve' watches and rebuilds the application.

  2. And My library is dependent on materialize-css and I need to import its scss files into lib's global scss, but this is not working until I installed the materialize-css to my application project. Is this the only way? >> Looks like you were able to solve this by updating the library's ng-package.json

  3. As I am using the scss-bundle and this will bundle all the scss files into one but there is an scss files that imports some resources like

@font-face { font-family:"Roboto Regular"; font-weight:normal; font-style:normal; src: url("../../resources/fonts/roboto-regular/Roboto-Regular.eot?") format("eot"), / IE9 Compat Modes / url("../../resources/fonts/roboto-regular/Roboto-Regular.woff") format("woff"), / Pretty Modern Browsers / url("../../resources/fonts/roboto-regular/Roboto-Regular.ttf") format("truetype"); / Safari, Android, iOS / / url("../../resources/fonts/roboto-regular/Roboto-Regular.svg#Roboto-Regular") format("svg"); / / Legacy iOS / }

and I copied the resources folder as well but as there is only one bundled scss file for all scss (no folder hierarchy) so ../../resources fails as there need only one ../resources, what is the proposed solution ?

I struggled with paths too but i was able to fix the issues eventually. Do you still have this issue?

ermarkar commented 5 years ago

this is how i done this https://stackoverflow.com/questions/54003034/scss-compilation-issue-in-angular-lib-created-using-angular-cli

jbojcic1 commented 5 years ago

Excellent discussion here! I can already see a few workarounds which seem reasonable. Although I'd discourage global styles in libraries, if your use case require such I'd recommend you to look at ngx-build-plus. You can customize your build using it.

Closing the issue here. If you think we're missing something and it's essential for the CLI to support this out of the box (i.e., you have use cases that we have thought about), please open a new issue.

@mgechev angular material and cdk are examples of libs which use global styles. If you use cdk in your lib and need to override something how would you do it without the global styles? Or If your lib uses material and wants to provide custom theme? Also ngx-build-plus doesn't seem to have support for libraries at all at the moment.

JanneHarju commented 5 years ago

To overcome this situation :

  • Use Angular-cli 7.1 which has a new option (--deleteOutputPath=false) and use the rimraf command to enrue dist cleaning is proceeded before any other script is executed.

It seems that this options is taken away from cli in Angular CLI: 7.3.1 version. I didn't find any information about it and didn't find any replacement for this options. So I started use wait-on package to wait until package-name.d.ts file is ready until to start scss-bundle.

And for others trying to find -w options in scss-bundle you should update your package to 2.5.0-beta. It is new feature of that package.

JanneHarju commented 5 years ago

To overcome this situation :

  • Use Angular-cli 7.1 which has a new option (--deleteOutputPath=false) and use the rimraf command to enrue dist cleaning is proceeded before any other script is executed.
  • If using previous Angular version : add a short delay before using cpx, scss-bundle (using npm package like @sindresorhus delay-cli)

I'm still wondering how your solution can even work with library because if I am understand correctly there is no --delete-output-path parameter with ng-packagr like normal angular application has. Check this out https://github.com/ng-packagr/ng-packagr/issues/632 So I'm stuck with your other suggestion.

EDIT: I research more and notice that they have implemented deleteDestPath in ng-packagr. I read wrong that ng-packagr issue history. It was merged and implemented, but still even I use deleteDestPath(ng-packagr parameter name) or deleteOutputPath (angular cli parameter name) both give me this error "Data path "" should NOT have additional properties(deleteDestPath || deleteOutputPath)" So it seems that it is not working with libraries only with application.

Angular CLI: 7.3.3
Node: 10.15.0
OS: win32 x64
Angular: 7.2.6
... animations, common, compiler, compiler-cli, core, forms
... http, language-service, platform-browser
... platform-browser-dynamic, router, service-worker

Package                            Version
------------------------------------------------------------
@angular-devkit/architect          0.13.1
@angular-devkit/build-angular      0.13.1
@angular-devkit/build-ng-packagr   0.13.1
@angular-devkit/build-optimizer    0.13.1
@angular-devkit/build-webpack      0.13.1
@angular-devkit/core               7.3.1
@angular-devkit/schematics         7.3.3
@angular/cdk                       7.3.3
@angular/cli                       7.3.3
@angular/flex-layout               7.0.0-beta.19
@angular/material                  7.3.3
@ngtools/json-schema               1.1.0
@ngtools/webpack                   7.3.1
@schematics/angular                7.3.3
@schematics/update                 0.13.3
ng-packagr                         4.7.0
rxjs                               6.3.3
typescript                         3.1.3
webpack                            4.29.0
angular-automatic-lock-bot[bot] commented 5 years ago

This issue has been automatically locked due to inactivity. Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.