I have setup my Angular 2 project in .NET Core solution and I have a situation where I need to use .cshtml view files to be rendered from server and use them as templates in Angular components. I am using webpack to AOT bundle them.
How can I exclude templateUrl or template to be excluded (not to be compiled into output .js file) but rather resolved on the fly?
My lazy load component (notfound.component.ts):
import { Component } from "#angular/core";
#Component({
templateUrl: "/Home/PageNotFound" // This is my Controller/Action
})
export class NotFoundComponent
{
}
webpack.config.js:
var webpack = require("webpack");
var clean = require("clean-webpack-plugin");
var compression = require("compression-webpack-plugin");
var path = require("path");
var analyzer = require("webpack-bundle-analyzer").BundleAnalyzerPlugin;
var HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
"app": "./Client/main-aot.ts" // AoT compilation
},
devtool: "source-map",
output: {
path: __dirname + "/wwwroot/dist/bundle",
//filename: "[name]-[hash:8].bundle.js",
filename: "[name].js",
chunkFilename: "[id]-[hash:8].chunk.js",
publicPath: "/dist/bundle/",
},
resolve: {
extensions: [".ts", ".js"]
},
module: {
rules: [
{
test: /\.ts$/,
use: [
"awesome-typescript-loader",
"angular-router-loader?aot=true&genDir=aot/"
]
}
],
exprContextCritical: false
},
plugins: [
new clean(
[
__dirname + "/wwwroot/dist/bundle"
]
),
new analyzer(),
new webpack.LoaderOptionsPlugin({
minimize: true,
debug: false
}),
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
},
output: {
comments: false
},
sourceMap: true
}),
new compression({
asset: "[path].gz[query]",
algorithm: "gzip",
test: /\.js$|\.html$/,
threshold: 10240,
minRatio: 0.8
})
]
};
When I run following NPM command, its giving me error:
"node_modules/.bin/ngc -p tsconfig-aot.json" && webpack --configebpack.config.js
Error: Compilation failed. Resource file not found:
C:/Users/Saad/Documents/Visual Studio 2017/Projects/HelloAngular/HelloAngular/Client/notfound/dist/template/notfound/notfound.html
Related
How do I configure ASP.NET Core MVC (.NET6) (MPA) to run "Vue.js" with Webpack?
I would like to build a multi-page application(MPA) without using SPA in ASP.NET Core MVC.
I want the project configuration to be close to the default configuration. (Divided into wwwroot, Controllers and Views)
// ASP.NET Core MVC (.NET6) Project structure
Project
- wwwroot
- css (omit)
- dist
main.js
- js
- views
- Test1
- index.js // Import does not work
- node_modules
- vue
- ...
- src
- index.html
- index.js
- Controllers
- Test1Controller.cs
- Views
- Test1
- Index.cshtml
Do not use ".vue" files.
Currently, you can set webpack-config.js as below and run up to "npm run build".
I'm having a problem because import doesn't work in the javascript to be executed.
// /wwwroot/webpack-congig.js
const path = require("path");
const webpack = require("webpack");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const { VueLoaderPlugin } = require("vue-loader");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
entry: {
main: "./src/index.js",
Test1: "./js/views/Test1/index.js"
},
output: {
filename: "[name].js",
path: __dirname + "/dist"
},
devtool: "source-map",
mode: "development",
module: {
rules: [
{
test: /\.js$/,
loader: "babel-loader",
include: path.resolve(__dirname, "/js"),
options: { presets: ["#babel/preset-env"] }
},
{
test: /\.vue$/,
loader: "vue-loader"
},
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, "css-loader"],
}
],
},
resolve: {
alias: {
"vue$": path.resolve("./node_modules/vue/dist/vue.esm-bundler.js")
},
extensions: ["*", ".js", ".vue"],
},
plugins: [
new HtmlWebpackPlugin({
template: "./src/index.html",
}),
new MiniCssExtractPlugin({
filename: "./css/site.css",
chunkFilename: "[name].css"
}),
new VueLoaderPlugin(),
new webpack.DefinePlugin({
__VUE_OPTIONS_API__: false,
__VUE_PROD_DEVTOOLS__: false,
})
],
};
// /wwwroot/src/index.js
import "../node_modules/vue";
console.log("The site bundle has been loaded!");
// /wwwroot/js/views/Test1/index.js
// Import does not work
import { createApp } from "vue";
const app = createApp({
});
app.mount("#app");
This is the error:
'node"' is not recognized as an internal or external command,
operable program or batch file.
[Finished in 0.139s]
Also, this is coming from atom text editor, if that's necessary information.
Here's my code:
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const HtmlWebpackInlineSourcePlugin = require('html-webpack-inline-source-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin')
const isProduction = process.env.npm_lifecycle_event === 'build'
module.exports = {
entry: './src',
// resolve: {
// alias: {
// 'src': path.join(__dirname, '/src'),
// 'libs': path.join(__dirname, '/src/libs'),
// }
// },
devtool: !isProduction && 'source-map',
output: {
path: path.join(__dirname, '/dist'),
},
module: {
rules: [
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader'
}
]
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: 'src/index.html',
// minify: isProduction && {
// collapseWhitespace: true
// },
minify: isProduction,
inlineSource: isProduction && '\.(js|css)$'
}),
new HtmlWebpackInlineSourcePlugin(),
new OptimizeCssAssetsPlugin({}),
new MiniCssExtractPlugin({
filename: '[name].css'
}),
new CopyWebpackPlugin([
{ from: './src/assets/**/*', to: path.join(__dirname, '/dist'), flatten: false, force: true },
]),
],
devServer: {
stats: 'minimal',
overlay: true,
contentBase: path.resolve('src/assets'),
// contentBase: path.join(__dirname, '/src/assets'),
}
}
Am I just missing a package for this, or is there an error in my quote, or what?
Mmmmm... how are you running the code?
Most probable answer, based on your provided info --> you have any node installation in your system and/or your node installation is not accesible or included into your path.
Check https://nodejs.org/en/download/
Taken from webpack docs:
Since webpack v5.0.0-beta.1 the minimum Node.js version to run webpack
is 10.13.0 (LTS)
You need to install node.js
Hi I'm building a React app with SSR. Server and client part both written in typescript and transpiled separately.
Here the app structure for the better understanding:
Here the simplified webpack configs for the server and client bundles:
// webpack.client.js
module.exports = {
mode: "development",
resolve: {
modules: ["src", "static", "node_modules"],
extensions: [".ts", ".tsx", ".js", ".jsx"],
},
entry: [
"./src/client/index.tsx"
],
output: {
filename: "bundle.js",
path: PUBLIC_PATH,
},
module: {
rules: [
{
test: /\.tsx?$/,
use: [
{
loader: "ts-loader",
}
],
},
]
},
plugins: [
new webpack.DefinePlugin({ IS_SERVER: false })
]
};
Server config looks pretty much the except for the target and externals
//webpack.server.js
const config = {
mode: "development",
resolve: {
modules: ["src", "static", "node_modules"],
extensions: [".ts", ".tsx", ".js", ".jsx"],
},
externals: [webpackNodeExternals()],
target: 'node',
entry: [
"./src/server/index.ts"
],
output: {
filename: "bundle.js",
path: SERVER_BUILD_PATH
},
module: {
rules: [
{
test: /\.tsx?$/,
use: [
{
loader: "ts-loader",
}
],
},
]
},
plugins: [
new webpack.DefinePlugin({ IS_SERVER: true })
]
};
In the server code I got a renderer function which renders React application to string.
// renderer.tsx
import React from "react";
import { renderToString } from "react-dom/server";
import { App } from "client/App";
const html = (app) => `
<html>
<head>
</head>
<body>
<div id="root">${app}</div>
<script src="/public/bundle.js"></script>
</body>
</html>
`;
export async function renderer(req) {
const app = renderToString(<App />);
return html(app);
}
Which then returns to the client by the express server.
//index.ts
app.get("*", async (req, res) => {
const content = await renderer(req);
res.send(content);
});
As you see both parts need to transpile React app. The question is - how can I reuse transpiled client code in the server bundle so that server config only need to transpile index.ts and renderer.tsx?
You can use webpack-merge package to do that
Here is my example
const merge = require('webpack-merge');
const baseConfig = require('./webpack.config.js');
const webpack = require("webpack");
module.exports = merge(baseConfig, {
plugins: [
new webpack.DefinePlugin({
'process.env': {
'NODE_ENV': JSON.stringify('development'),
'BASE_URL': JSON.stringify('http://localhost:5000/')
}
})
],
watch: true
});
This can be easily done using resolve.alias:
https://webpack.js.org/configuration/resolve/#resolvealias
Simply move the helpers directory up in the app's directory hierarchy and import from it.
In your case, I would also like to redesign the app using a single webpack.config.js file at the root level of your app in which you can combine the client and server configurations using the multi-compiler feature and respect the principle "Do not repeat yourself":
https://stackoverflow.com/a/43689505/2569746
I'm using babel-plugin-react-css-modules and it seems to be creating the className/styleName, but for some reason it isn't outputting the CSS so that it can be read by the module.
Here's my application: launchpad
I'm using webpack 4.2.0/React 16 and use a babel configuration in the webpack.config imported from a separate config file as you can't set context in .babelrc.
here's the babel config:
{
loader: 'babel-loader',
options: {
'plugins': [
'react-hot-loader/babel',
'transform-runtime',
'transform-object-rest-spread',
'transform-class-properties',
['react-css-modules',
{
context: paths.javascript,
'generateScopedName': '[name]__[local]___[hash:base64:5]',
'filetypes': {
'.scss': {
'syntax': 'postcss-scss',
'plugins': ['postcss-nested']
}
},
'exclude': 'node_modules',
'webpackHotModuleReloading': true
}
]
],
'presets': [
'env',
'react',
'flow'
],
'env': {
'production': {
'presets': ['react-optimize']
}
}
}
}
And here is my webpack:
const webpack = require('webpack')
const path = require('path')
const paths = require('./webpack/config').paths
const outputFiles = require('./webpack/config').outputFiles
const rules = require('./webpack/config').rules
const plugins = require('./webpack/config').plugins
const resolve = require('./webpack/config').resolve
const IS_PRODUCTION = require('./webpack/config').IS_PRODUCTION
const IS_DEVELOPMENT = require('./webpack/config').IS_DEVELOPMENT
const devServer = require('./webpack/dev-server').devServer
const DashboardPlugin = require('webpack-dashboard/plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
// Default client app entry file
const entry = [
'bootstrap-loader/extractStyles',
path.join(paths.javascript, 'index.js')
]
plugins.push(
// Creates vendor chunk from modules coming from node_modules folder
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
filename: outputFiles.vendor,
minChunks (module) {
const context = module.context
return context && context.indexOf('node_modules') >= 0
}
}),
// Builds index.html from template
new HtmlWebpackPlugin({
template: path.join(paths.source, 'index.html'),
path: paths.build,
filename: 'index.html',
minify: {
collapseWhitespace: true,
minifyCSS: true,
minifyJS: true,
removeComments: true,
useShortDoctype: true
}
})
)
if (IS_DEVELOPMENT) {
// Development plugins
plugins.push(
// Enables HMR
new webpack.HotModuleReplacementPlugin(),
// Don't emmit build when there was an error while compiling
// No assets are emitted that include errors
new webpack.NoEmitOnErrorsPlugin(),
// Webpack dashboard plugin
new DashboardPlugin()
)
// In development we add 'react-hot-loader' for .js/.jsx files
// Check rules in config.js
rules[0].use.unshift('react-hot-loader/webpack')
entry.unshift('react-hot-loader/patch')
}
// Webpack config
module.exports = {
devtool: IS_PRODUCTION ? false : 'eval-source-map',
context: paths.javascript,
watch: IS_DEVELOPMENT,
entry,
output: {
path: paths.build,
publicPath: '/',
filename: outputFiles.client
},
module: {
rules
},
resolve,
plugins,
devServer
}
If you run npm start or yarn start the code will compile and run, and you can see a basic application layout. If you inspect the react code you will see that the style name is reflected in the component. What doesn't happen is that the style isn't being output. I can't seem to figure out why.
Any help is appreciated.
So I downloaded a theme that has a bunch of less files but there is a main one that imports the others in the correct order. It came with a gulp file that watches any .less file but recompiles only the one that imports all the others. It looks like so:
gulp.task('less', function () {
return gulp.src(Paths.LESS_TOOLKIT_SOURCES)
.pipe(sourcemaps.init())
.pipe(less())
.pipe(autoprefixer())
.pipe(sourcemaps.write(Paths.HERE))
.pipe(gulp.dest('dist'))
})
My webpackconfig so far looks like the following:
// Things I still need to do:
// 1) Add uglifier plugin for minification
var path = require('path');
var webpack = require('webpack');
var cssnext = require('cssnext');
var cssimport = require('postcss-import');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var isProd = process.env.NODE_ENV === 'production' ? true : false;
module.exports = {
devtool: 'eval',
entry: [
'webpack-dev-server/client?http://localhost:3000',
'webpack/hot/only-dev-server',
'./app/index'
],
stylePath: path.resolve(__dirname, 'app', 'style'),
postcss: function () {
return [
cssimport({
path: './app/style/index.css',
onImport: function (files) {
files.forEach(this.addDependency)
}.bind(this)
}),
cssnext()
]
},
output: {
path: path.join(__dirname, 'dist'),
filename: 'bundle.js',
cssFilename: 'style.css',
publicPath: '/static/'
},
plugins: [
new ExtractTextPlugin('style.css', {
allChunks: true
}),
new webpack.HotModuleReplacementPlugin()
],
module: {
loaders: [{
test: /\.js$/,
loaders: ['react-hot', 'babel'],
include: path.join(__dirname, 'app')
},
{
test: /\.css$/,
loader: isProd ? ExtractTextPlugin.extract('style', 'css? modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!postcss') : 'style!css?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!postcss'
},
{
test: /\.less$/,
loader: "style!css!less"
}]
},
resolve: {
root: path.resolve(__dirname),
extensions: [
'',
'.js',
'.css'
],
modulesDirectories: [
'app',
'node_modules'
]
}
};
I am trying to accomplish the the same thing but with webpack. I have installed and setup the less-loader like the guide says but it tries to compile all of the files. Is there a way to set it up like the gulp file that will watch any file but only compile a specific file? I have this working in brunch when working in Phoenix but I trying to switch brunch out with webpack for phoenix.
In brunch I just told it to ignore the folder with the less files and then had the main less file outside that directory so brunch would only compile the main less file and import the others.