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

Feature Request: Copy assets outside of src folder (e.g. node_modules) #3555

Closed
serhiisol opened this issue Dec 14, 2016 · 31 comments
Closed
Assignees
Labels
P3 An issue that is relevant to core functions, but does not impede progress. Important, but not urgent

Comments

@serhiisol
Copy link
Contributor

serhiisol commented Dec 14, 2016

So this is a feature request for ability to copy assets from different folders of the project, e.g. node_modules etc. Currently it doesn't seem to be supported even if you'll specify this:

angular-cli.json

    "assets": [
      "assets",
      "../logo.png",
      "../node_modules/third-party/cool.svg"
    ],

It's actually common use case, when you need to copy assets from third-party modules from node_modules

Below you can see additional information about cli and steps to reproduce:

OS?

Windows 7, 8 or 10. Linux (which distribution). Mac OSX (Yosemite? El Capitan?)
macOS Sierra 10.12.1

Versions.

Please run ng --version. If there's nothing outputted, please run in a Terminal: node --version and paste the result here:

angular-cli: 1.0.0-beta.21
node: 7.2.1
os: darwin x64

Repro steps.

Was this an app that wasn't created using the CLI? What change did you do on your code? etc.
To reproduce this issue just try to copy file one level up of src folder or explicitly from node_modules

Stack trace

  1. If you'll specify asset as
   "assets": [
      "assets",
      "../node_modules/bootstrap-theme/svg/sprite-symbol.svg"
    ]

you won't see any stack trace, all good, but file won't be copied

  1. If you'll specify asset as
   "assets": [
      "assets",
      "node_modules/bootstrap-theme/svg/sprite-symbol.svg"
    ]
ENOENT: no such file or directory, stat '/Users/serhiisol/Development/test-app/src/node_modules/bootstrap-theme/svg/sprite-symbol.svg'
Error: ENOENT: no such file or directory, stat  #'/Users/serhiisol/Development/test-app/src/node_modules/bootstrap-theme/svg/sprite-symbol.svg'
    at Object.fs.statSync (fs.js:906:18)

Mention any other details that might be useful.

What if you want to include assets from node_modules, which seems like a fairly common use case

@hikalkan
Copy link

We also need this to copy a file from node_modules to output folder.

@manuelfink
Copy link

Same situation here. It would be awesome if angular-cli could merge several sources into joined the public foulders eg.:

"assets":[
"source1/css",
"source1/js",
"source2/css",
"source2/js"
]

output is merged in public folders /css and /js.

It also would be really handy do specify different targets to avoid naming conflicts eg.

assets: [
  { "source":"../node_modules/awsomse/style.css", "to":"css/awesome.css"},
  { "source":"../node_modules/other/style.css", "to":"css/other.css"}
]

@filipesilva
Copy link
Contributor

There was something similar to @manuelfink's suggestion added for scripts/styles in #3402.

Something similar could be added for assets.

@filipesilva filipesilva self-assigned this Dec 30, 2016
@filipesilva filipesilva added command: build P3 An issue that is relevant to core functions, but does not impede progress. Important, but not urgent labels Dec 30, 2016
@serhiisol
Copy link
Contributor Author

@filipesilva is it available in beta.24 ? if so I can test

@filipesilva
Copy link
Contributor

@serhiisol it doesn't exist for assets, just for scripts/styles.

@serhiisol
Copy link
Contributor Author

@filipesilva right, ok, I can try to help with it

@filipesilva
Copy link
Contributor

@serhiisol I'd prefer to take this one myself since it requires a few changes throughout parts of the app that I already had to do for other PRs. I might end up consolidating that mechanism.

@derekcdaley
Copy link

What's the latest on this? This would be an amazing feature.

@mcgraphix
Copy link

Any update on this? It's really unfortunate that you manually have to copy the files from npm deps into your own assets directory. Especially given that there is no way to add any custom scripts into the build that could do this automatically.

@fleskesvor
Copy link

@mcgraphix I agree that it's unfortunate that we can't currently configure external assets in angular.cli.json, but you can easily add a custom script to package.json to copy assets. I have this one added to copy the svg file from Octicons:

"copy:assets": "cp node_modules/octicons/build/sprite.octicons.svg src/assets",

(Use a module like eg. copyfiles if you want cross-platform copy.)

If you launch your project with npm start, you might want to append npm run copy:assets && in front of whatever is there from before.

I currently only use it for that one file, but you could do the same for all of your external assets until a better solution is implemented.

@Bnaya
Copy link

Bnaya commented Feb 4, 2017

Looks like you can use explicit file-loader calls!

// this will include static files from budgetkey-ng2-components to our dist
const t = '';
console.log(require('file-loader?name=assets/[path]/[name].[ext]!budgetkey-ng2-components/assets/' + t));

I'm still hacking on it

@hansl hansl assigned hansl and unassigned filipesilva Feb 10, 2017
@filipesilva filipesilva assigned filipesilva and unassigned hansl Feb 13, 2017
filipesilva added a commit to filipesilva/angular-cli that referenced this issue Feb 14, 2017
Fix angular#3555

BREAKING CHANGE: 'assets' as a string in angular-cli.json is no longer allowed, use an array instead.
@jeff-jacobs
Copy link

I just wanted to thank @filipesilva for getting this feature in. Thanks man!

@filipesilva
Copy link
Contributor

@jeffaxial glad you're finding it useful!

@fleskesvor
Copy link

Thanks, @filipesilva!

If I understand the documentation right, I have to configure something like

{ "glob": "**/*", "input": "../node_modules/octicons/build/svg", "output": ["./assets", "../src/assets/"] }

for my own use-case if I want to have the Octicons svg files available both during development and in the production build. Is that right?

@filipesilva
Copy link
Contributor

@fleskesvor that sounds mostly right, except output shouldn't be an array. It should be the location where you want them to be on a build.

@fleskesvor
Copy link

@filipesilva Yes, you're absolutely right, of course. The reason why that appeared to be working must have been that I had already built my project using the correct syntax. On a new project with angular-cli up to date (v. 1.0.0-rc.1), this configuration works:

{ "glob": "**/*", "input": "../node_modules/octicons/build/svg", "output": "./assets/" }

Both during development and an AoT build.

asnowwolf pushed a commit to asnowwolf/angular-cli that referenced this issue Apr 12, 2017
Fix angular#3555
Close angular#4691

BREAKING CHANGE: 'assets' as a string in angular-cli.json is no longer allowed, use an array instead.
@fletchsod-developer
Copy link

fletchsod-developer commented May 5, 2017

I tried that option '{ "glob": "**/*", "input": "../../foo", "output": "_artifacts/foo"' then ran "ng build" and it doesn't do anything.

@fleskesvor
Copy link

@fletchsod-developer It's working for me in version 1.0.0-rc.1. Which version are you on, and are you 100% sure of that input path?

@rajramo61
Copy link

@filipesilva I am using @angular/cli: 1.0.4
and trying like
"assets": [
{ "glob": "/*", "input": "../node_modules/styles/lib/modern/assets/images/", "output": "./assets/" },
{ "glob": "
/", "input": "../node_modules/styles/lib/modern/assets/images/", "output": "../src/assets/" },
{ "glob": "**/
", "input": "../node_modules/styles/lib/modern/assets/fonts/", "output": "./assets/" },
{ "glob": "**/*", "input": "../node_modules/styles/lib/modern/assets/fonts/", "output": "../src/assets/" }
]

But it does not copy anything.

@codedmonkey
Copy link

The idea of this feature is great, but it seems that this solution doesn't work for the development environment at all. I would like to use this feature to include CSS from a node_modules directory, but if I'm unable to access the files while developing the app this doesn't seem to be the way to solve that problem. So am I missing something here or is this feature just for show?

@jeff-jacobs
Copy link

jeff-jacobs commented Jul 7, 2017

Honestly, it's a little bit rude to assume they've spent time on a feature that only looks like it works.

I'm using it locally while developing my app as well in a production environment, and it works great.

Here is how I am using it:
I have a folder with font files in it I want to get from a node_module directory to my assets folder.
Input folder: node_modules/DIRECTORY/fonts
Output folder: assets/fonts

In .angular-cli.json:
"assets": [ "assets", { "glob": "**/*", "input": "../node_modules/DIRECTORY/fonts", "output": "./assets/fonts" } ]

Do note that you need to restart ng serve after adding the line. All I can say is that I have this working on several projects, and it works just as advertised.

@fleskesvor
Copy link

Yep, as noted by me just a few comments up, I also have it working both in development and production.

@rajramo61
Copy link

But, I am facing the problem.
I have few external stylesheets which I am pulling from ../node_modules/dir/stylesheet . I am also using stylePreprocessorOptions to include few paths for pre processing otherwise it fails here itself.
These styles use some fonts and images which are available under ../node_modules/dir/stylesheets/fonts and ../node_modules/dir/stylesheets/images . The failure shows it is looking for assets under src/assets .

Error is like the following:
Module not found: Error: Can't resolve './assets/images/loading-icon.svg' in 'project-path/src' . It is repeated for each image/fonts referenced in stylesheet.

I provided the option using glob to copy assets but it does not copy it. It seems styles processing happens before copy and it tries to reference the fonts and images so it just fails and could not copy (Just a guess).

@hieunt88
Copy link

@filipesilva Work like a charm! Thanks for putting in the work. I almost pull in Gulp to copy a few files from node_modules.

@rajramo61 for stylesheets, if you use SASS/LESS, you can use the import statement without having to copy them over. Also, can you post your "apps" section in .angular-cli.json for further troubleshooting?

@rajramo61
Copy link

@hieunt88
Currently, my work around is to run a copy script to copy fonts or images from node styles folder to src/assets to mitigate this issue as this does not work for me.

Here is the app section.
{
"root": "src",
"outDir": "dist",
"assets": [
"assets",
{ "glob": "/*", "input": "../node_modules/styleg/lib/modern/assets/fonts/", "output": "../src/assets/fonts" },
{ "glob": "
/*", "input": "../node_modules/style/lib/modern/assets/images/", "output": "../src/assets/images" }
],
"index": "index.html",
"main": "main.ts",
"polyfills": "polyfills.ts",
"test": "test.ts",
"tsconfig": "tsconfig.app.json",
"testTsconfig": "tsconfig.spec.json",
"prefix": "app",
"styles": [
"styles.scss"
],
"stylePreprocessorOptions": {
"includePaths": [
"../node_modules",
"../node_modules/bourbon/app/assets/stylesheets",
"../node_modules/bourbon-neat/app/assets/stylesheets"
]
},
"scripts": [],
"environmentSource": "environments/environment.ts",
"environments": {
"dev": "environments/environment.ts",
"prod": "environments/environment.prod.ts"
}
}

style.scss has
@import "~style/modern"; // this is importing styles from node module.

This modern is again combination of multiple scss files which are pre-build and I need to use them.
It breaks mostly, as in one of the scss file has a variable
$font-path: 'assets/fonts/';

This variable is utilized in many places for the path for fonts. Like
@at-root {
@font-face {
font-family: "demo-icons";
src: url("#{$font-path}demo-icons.svg");
url("#{$font-path}demo-icons.woff") format("woff"),
font-weight: normal;
font-style: normal;
}
}
I see errors like following for all the files referred from font or image directories:
ERROR in ./src/assets/fonts/demo-icons.svg
Module build failed: Error: ENOENT: no such file or directory, open '//src/assets/fonts/demo-icons.svg'

I tried to override this variable $font-path but could not make it work.

@hieunt88
Copy link

hieunt88 commented Sep 6, 2017

@rajramo61 this is my script to copy external fonts. glob is different and will match all sub file/folder paths. This should work.

{ "glob": "**/*", "input": "../node_modules/font-awesome/fonts", "output": "./assets/fonts/" }

For $font-path, I ran into the same issue. Angular CLI would try to resolve asset paths, in your case ./src/assets/fonts/demo-icons.svg, during SCSS compiling process and fail if they don't exist. I have yet to find a way to change this behaviour. My work around is to copy the assets to the assets folder using another pre-build script e.g gulp.

Also, you need to drop src from your $font-path like so.

$font-path: 'assets/fonts/'

For SASS, I believe the problem is not with Angular CLI referencing external .scss. The build most likely broke because of the asset path issue above. Try the setting below.

"stylePreprocessorOptions": {
   "includePaths": [
     "../node_modules/path/to/modern/scss"
  ]
}

Then, in your styles.scss.

$font-path: 'assets/fonts/'
@import 'modern';

@ghiscoding
Copy link

ghiscoding commented Dec 14, 2017

That doesn't seem to work with JSON files (to use with ngx-translate), I tried multiple ways and it doesn't do anything. This is what I tried so far

"assets": [
        "assets",
        "favicon.ico",
        { "glob": "**/*", "input": "../node_modules/angular-slickgrid/i18n", "output": "./assets/i18n/" },
        { "glob": "*", "input": "../node_modules/angular-slickgrid/i18n", "output": "./assets/i18n/" },
        { "glob": "*/", "input": "../node_modules/angular-slickgrid/i18n", "output": "./assets/i18n/" },
        { "glob": "**/*", "input": "../node_modules/angular-slickgrid/i18n", "output": "./assets/i18n" }
      ],

Would that work with JSON files or is that a restricted file type?

@commercialsuicide
Copy link

commercialsuicide commented May 7, 2018

As @ghiscoding mentioned above, looks like it doesn't work with JSON files.
Angular 5.0.3
It will be pretty useful to allow copying of JSON files too, this way we can include different lists and other stuff from external libraries.

@tnicola
Copy link

tnicola commented Jul 13, 2018

@ghiscoding Have you tried with:

{ "glob": "**/*.json", "input": "node_modules/angular-slickgrid/i18n", "output": "/assets/i18n/" }

@kylietmo
Copy link

This does not appear to work with ng serve in Angular 8:

"assets":[
    {"glob": "jquery/dist/jquery.js", "input": "node_modules", "output": "third_party"}
]

It will work fine with ng build, but specifically not with ng serve.

@angular-automatic-lock-bot
Copy link

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.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Sep 21, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
P3 An issue that is relevant to core functions, but does not impede progress. Important, but not urgent
Projects
None yet
Development

Successfully merging a pull request may close this issue.