问题
Upon building & packaging an Angular 6 library, I can't seem to be able to instruct the Angular CLI to copy the library's assets into the dist/assets
folder on every build.
Assuming the project's folder structure is this -
- dist
- e2e
- node_modules
- projects
- lib1
- src
- lib
- assets
- icons
- src
When I run ng build lib1
or ng build lib1 --prod
the assets/icons
folder is not being copied into dist/lib1/assets/icons
.
If I run ng build
then src/assets
(the root src/assets) is being copied but not projects/lib1/assets
.
The angular.json
file contains a reference to "assets": ["src/assets"]
but it won't allow adding the assets
key specifically to the project, only to the main root app. When adding, I get the following error:
Schema validation failed with the following errors: Data path "" should NOT have additional properties(assets).
I also tried adding the following custom copy rule to the assets to copy the assets to dist/lib instead of to dist/appname:
"assets": [
"src/favicon.ico",
"src/assets",
{ "glob": "**/*", "input": "src/assets/icons", "output": "../lib1/assets/icons" }
],
But I get the following error:
An asset cannot be written to a location outside of the output path.
Is there a built-in way of managing library asset's copy on every build?
UPDATE 06/05/2018
I opened an issue with Angular CLI regarding this but have not heard back yet. Issue #11701
回答1:
Currently, I still have not found an official built-in way to do so.
I opened an Angular CLI issue and hopefully will get the CLI team response.
In the meantime my workaround is using command line tools:
In package.json
I added:
"scripts": {
...
"build": "ng build lib1 --prod && scss-bundle -c scss-bundle.config.json && cp -R projects/lib1/src/assets/ dist/lib1/assets/",
}
To copy the SASS files I use scss-bundle
with config file scss-bundle.config.json
that contains:
{
"entry": "./projects/lib1/src/assets/style/main.scss",
"dest": "./dist/lib1/assets/style/styles.scss"
}
This will build the SASS files of the project into 1 file and copy it into the dist folder. My SASS file structure is something like:
-- projects/lib1/src/assets/
-- style
-- main.scss
-- partials
-- _variables.scss
-- _styles.scss
__ _rtl.scss
So as you can see I don't want to ship all the raw sass, just one final file. Of course, you can also compile it into a .css
file instead.
To make sure all other assets are copied, I use a simple Mac OS/Linux command cp -R
or rsync
.
And, of course, instead of running ng build
I run npm run build
.
Hope this helps, and if you have a better solution please let me know.
回答2:
Looks like in the future this can all be automated with the CLI, however, for now, there are a few solutions out there. Some involved writing a post install script, which is a pretty good one if you have a ton of stuff going on. One involves manually moving them over, but that's just way too open for error IMO. I also have seen a couple of npm packages that you can install that seem to extend what ng-packagr does (ng-packagr builds your libraries and webpack builds your apps).
Some of these are good and some are bad, IMO, I won't go into what I think about them individually, instead I'll just share what I do.
I work on an enterprise Angular Application and I'm extracting our features and functionality into Libraries so we can start code sharing with mini-apps in the near future. Because of our processes and build protocols, we are already not using the ng cli directly to build our projects, instead we are using npm scripts.
If you are already familiar with NPM scripts, skip down below, otherwise, this quick note will be super helpful.
With the Angular CLI, you run something like these...
ng build myProject --configuration=production
to run a prod build of your project.
ng build myLibrary
to run a prod build of your library and you probably run ng build myLibrary --watch=true
to run a dev build of your library and watch for changes while you are working on the library.
For me, while I work on the project, I use the ng CLI, just as you do and run ng build myLibrary --watch=true
This works perfectly. I have an assets folder for my libraries that contain assets and I store them in myProject/src/lib/assets. All is well. My assets aren't in my dist/myLibrary though...but hey it's cool, because during development, when I use a relative path in my image tags <img>
webpack is pulling from my library project, not my dist folder anyhow. So how do I solve this with an NPM script? Well, when you read the next line, you're going to smack your forehead and go "crap, I knew that"...here goes...
IF SKIPPING, START HERE...
"myLibrary:prod": "ng build myLibrary && mkdir dist/myLibrary/lib/assets && cp -R projects/myLibrary/src/lib/assets/ dist/myLibrary/lib/assets/ && npm run msgAssetsCopied",
Yup, that's it, just some basic bash :)
I'll break it down for those that are new to the command line though.
myLibrary:prod
This is the name of the npm script aka npm run script. You call it in the command line with npm run myLibrary:prod
and let your terminal do the rest. The "rest" are simply commands your computer terminal can read, interpret and execute accordingly.
ng build myLibrary
this triggers the standard ng CLI build command, thus building your library
&&
this says "hey after you do the thing to the left of me [&&], do the thing to the right of me"
mkdir dist/myLibrary/lib/assets
this one is a basic bash command that creates a directory that you will be copying your assets over to. mkdir
makes a directory and the path designates where and what I want that directory to be. If I was in the folder I wanted a directory made in, say "foo", I would do mkdir bar
which would give me foo/bar
, if I was in "foo" and wanted the directory "tacos" to be in the "bar" directory, I would do mkdir bar/tacos
and it would create "tacos" in the "bar" directory like foo/bar/tacos
.
I prefer to make a folder and move assets from a -> b, rather than trying to cp a folder and it's assets.
cp -R projects/myLibrary/src/lib/assets/ dist/myLibrary/lib/assets/
this one is broken up into 4 parts for those new to bash.
cp
is "copy"-R
is for "recursive", meaning, take all files and folders and keep them the same structure once copied.projects/myLibrary/src/lib/assets/
this is where my assets are that I want to move over to that new directory I made with the previousmkdir
command earlier.dist/myLibrary/lib/assets/
is the destination for the copy command.
So with this one you have...
- Command
cp -R
- Target
path/to/assets/in/library/project/
- Destination
path/to/desired/directory/in/build
The last step is npm run msgAssetsCopied
which is just another npm script in my package.json that tells the person banging on the keyboard that the assets have been copied. I usually have messages throughout my scripts with emojis to make it easier for a dev to see exactly where a script is at any point in time by identifying emojis on the screen. For example...
"msgAssetsCopied": "echo '📁 Assets Copied to Library Dist Folder 📁'",
So 📁 Assets Copied to Library Dist Folder 📁
gets printed in terminal when we are done.
Still new? No worries, now I'll show you where they go in your package.json.
{
"name": "YourWorkspace",
"version": "0.0.0",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e",
}
}
As you can see, this is the top of your package.json file. You can add as many scripts as you need, below we'll drop in the one I just shared...
{
"name": "YourWorkspace",
"version": "0.0.0",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e",
"myLibrary:prod": "ng build myLibrary && mkdir dist/myLibrary/lib/assets && cp
-R projects/myLibrary/src/lib/assets/ dist/myLibrary/lib/assets/ && npm run
msgAssetsCopied",
}
}
Boom goes the dynamite!
来源:https://stackoverflow.com/questions/50595900/angular-6-building-a-library-with-assets