Reputation: 8122
I am trying to create a Blazor component in a Razor Class Library which uses npm dependencies. In my wwwroot
I created a package.json
:
{
"name": "mycomponent",
"version": "0.0.1",
"description": "",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "UNLICENSED",
"dependencies": {
"d3": "^5.14.2"
}
}
In my csproj
I have:
<Target Name="PreBuild" BeforeTargets="PreBuildEvent">
<Exec Command="npm install" WorkingDirectory="$(ProjectDir)wwwroot" />
</Target>
And I set my project to create a .nupkg.
When I now run dotnet publish MyComponent -c Release
, I get the MyComponent.1.0.0.nupkg
but its staticwebassets
folder only has the top level content of wwwroot
in there.
So, how do I get the dependencies from the node_modules
folder in there? Do I have to run some sort of packager which generates a minified package in the root folder or am I missing something different?
Upvotes: 4
Views: 5482
Reputation: 8122
I found a solution which adds webpack to the game. Here is how I did it:
package.json
, run npm init
inside wwwroot
to generate onewwwroot
but package.json
and package-lock.json
to wwwroot/src
Install webpack and some loaders:
npm install --save-dev webpack css-loader file-loader style-loader
Add an appropriate webpack.config.js
:
var path = require('path');
module.exports = {
mode: 'production',
entry: [ './src/main.js', './src/style.css' ],
module: {
rules: [
{ test: /\.css$/, use: [ 'style-loader', 'css-loader' ] },
{ test: /\.(jpe?g|png|gif|svg)$/i, use: 'file-loader' }
]
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'index.bundle.js',
publicPath: '_content/MyRazorClassLibrary/dist/' // << See note
}
};
Note: The publicPath
is used for rewriting the path when run inside Blazor. Webpack packs the result in a way that all assets are relative to the main JS file. However Blazor expects the data at the path _content/ProjectName
, which is accounted for using publicPath
.
csproj
file: <Target Name="PreBuild" BeforeTargets="PreBuildEvent">
<Exec Command="npm install" WorkingDirectory="$(ProjectDir)wwwroot" />
<Exec Command="webpack" WorkingDirectory="$(ProjectDir)wwwroot" />
</Target>
<ItemGroup>
<Content Remove="wwwroot\package-lock.json" />
<Content Remove="wwwroot\package.json" />
<Content Remove="wwwroot\src\**" />
<Content Remove="wwwroot\webpack.config.js" />
</ItemGroup>
<ItemGroup>
<None Include="wwwroot\package-lock.json" />
<None Include="wwwroot\package.json" />
<None Include="wwwroot\src\**" />
<None Include="wwwroot\webpack.config.js" />
</ItemGroup>
This will cause the src
directory and npm and webpack specific files to not be included in the final NuGet package. Plus, it'll run npm install
and webpack
.
For this to work, you must install webpack-cli
:
npm install -g webpack webpack-cli
Now, when you run dotnet build -c Release MyRazorClassLibrary
, and set your library to generate a NuGet package on build, you will get a nice nupkg
with everything baked in.
Upvotes: 4
Reputation: 13448
Sorry there is no support for this in Blazor. Your best approach is to document the requirements on external dependencies for anyone using the library.
I'd point out that not everyone uses NPM (I avoid it like the plague) and have different approaches to client-side packages, so if this is a "public" package it might be too prescriptive an approach to require NPM. If it's internal use only that's fine, but you're on your own as to how to handle bundling and packaging.
There is an issue tracking how static resources are handled
Upvotes: 1