Reputation: 619
I am trying to upgrade my angular 5, webpack 2.2 project to angular 7 with webpack 4.4. Here's my updated package.json:
"dependencies": {
"@angular/animations": "^7.1.0",
"@angular/cdk": "^7.1.0",
"@angular/common": "^7.1.0",
"@angular/compiler": "^7.1.0",
"@angular/compiler-cli": "^7.1.0",
"@angular/core": "^7.1.0",
"@angular/flex-layout": "7.0.0-beta.19",
"@angular/forms": "^7.1.0",
"@angular/http": "^7.1.0",
"@angular/material": "^7.1.0",
"@angular/platform-browser": "^7.1.0",
"@angular/platform-browser-dynamic": "^7.1.0",
"@angular/platform-server": "^7.1.0",
"@angular/router": "^7.1.0",
"@types/chart.js": "^2.7.20",
"@types/datatables.net": "1.10.13",
"@types/handsontable": "^0.35.0",
"@types/jquery": "^3.3.5",
"@types/node": "^10.12.10",
"angular2-csv": "^0.2.9",
"aspnet-prerendering": "^3.0.1",
"aspnet-webpack": "^3.0.0",
"bootstrap": "^3.3.7",
"chart.js": "^2.7.2",
"core-js": "2.5.7",
"css": "^2.2.4",
"d3": "^4.7.3",
"datatables.net": "^2.1.1",
"datatables.net-bs": "^2.1.1",
"datatables.net-select": "^1.2.7",
"datatables.net-select-bs": "^1.2.7",
"es6-shim": "^0.35.1",
"event-source-polyfill": "1.0.4",
"expose-loader": "^0.7.5",
"isomorphic-fetch": "^2.2.1",
"jquery": "3.3.1",
"json-loader": "^0.5.7",
"ng2-handsontable": "^2.1.0-rc.3",
"popper.js": "^1.14.6",
"preboot": "6.0.0-beta.6",
"reflect-metadata": "0.1.10",
"rxjs": "^6.3.3",
"rxjs-compat": "^6.3.3",
"shepherd.js": "2.0.0-beta.35",
"to-string-loader": "^1.1.5",
"typescript-watcher": "0.0.4",
"url-loader": "1.1.2",
"webpack-hot-middleware": "^2.24.3",
"zone.js": "^0.8.26"
},
"devDependencies": {
"@types/jasmine": "3.3.0",
"angular2-template-loader": "^0.6.0",
"awesome-typescript-loader": "^5.2.1",
"css-loader": "0.28.11",
"extract-text-webpack-plugin": "^4.0.0-beta.0",
"file-loader": "^2.0.0",
"html-loader": "1.0.0-alpha.0",
"html-webpack-plugin": "^4.0.0-beta.4",
"jasmine-core": "^3.3.0",
"karma": "^3.1.1",
"karma-chrome-launcher": "^2.2.0",
"karma-jasmine": "^2.0.1",
"karma-sourcemap-loader": "^0.3.7",
"karma-webpack": "^4.0.0-rc.4",
"null-loader": "^0.1.1",
"raw-loader": "0.5.1",
"rimraf": "^2.5.2",
"style-loader": "0.20.3",
"typescript": "3.1.6",
"webpack": "4.4.1",
"webpack-cli": "2.0.12",
"webpack-dev-server": "^3.1.10",
"webpack-merge": "^4.1.4"
}
I have tried various loaders for loading the HTML (some are still included in package.json). I used loaders like raw-loader and to-string-loader to see if it would make any difference (which it does not).
Here's my webpack common config:
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var helpers = require('./helpers');
module.exports = {
entry: {
'polyfills': './ClientApp/polyfills.ts',
'vendor': './ClientApp/vendor.ts',
'app': './ClientApp/main.ts'
},
resolve: {
extensions: ['.ts', '.js']
},
module: {
rules: [
{
test: /\.ts$/,
loaders: [
{
loader: 'awesome-typescript-loader',
options: { configFileName: helpers.root('ClientApp', 'tsconfig.json') }
} , 'angular2-template-loader'
]
},
{
test: /\.html$/,
use: [{
loader: 'html-loader'
}] //'to-string-loader',
},
{
test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/,
loader: 'file-loader?name=assets/[name].[hash].[ext]'
},
{
test: /\.css$/,
exclude: helpers.root('ClientApp', 'app'),
loader: ExtractTextPlugin.extract({ fallback: 'style-loader', use: 'css-loader?sourceMap' })
},
{
test: /\.css$/,
include: helpers.root('ClientApp', 'app'),
loader: 'css-loader' //['raw-loader', 'to-string-loader']
}
]
},
optimization:
{
splitChunks: {
cacheGroups: {
commons: {
test: /[\\/]node_modules[\\/]/,
name: "vendors",
chunks: "all"
}
}
}
},
plugins: [
new webpack.ContextReplacementPlugin(
/angular(\\|\/)core(\\|\/)fesm5/,
helpers.root('ClientApp'), //./
{}
),
new HtmlWebpackPlugin({
template: 'Views/Home/Index.cshtml'
})
]
};
This is how I include all templates for my components:
@Component({
selector: "app",
template: require("./app.component.html"),
styles: ["./app.component.css"]
})
(Used to be templateUrl: "./app.component.html", which seems to make no difference)
Now I am stuck on this error:
I hope somebody can help me with this, since i have been stuck on this error for a week now. Thank you!
EDIT
When I use "styleUrls" instead of "styles" a somewhat similar error is shown:
Uncaught Error: Expected 'styles' to be an array of strings.
Upvotes: 2
Views: 5915
Reputation: 306
If anyone stumbled upon this, you should use native angular '@ngtools/webpack' plugin as a loader instead of 'angular2-template-loader':
const { AngularWebpackPlugin } = require('@ngtools/webpack');
...
module: {
rules: [
{
test: /\.tsx?$/,
loader: '@ngtools/webpack'
},
...
]
},
plugins: [
new AngularWebpackPlugin({
jitMode: true, // false=AOT by default
}),
...
]
In JIT mode it works similar to angular2-template-loader and uses raw-loader during runtime, but AOT mode is preferrable. More at https://www.npmjs.com/package/@ngtools/webpack The problem is that in AOT mode most of angular compilerOptions don't work (defaultEncapsulation in particular) - Angular uses default values (as of 12.0.0-rc.1)
Upvotes: 0
Reputation: 2668
The error likely has something to do with incompatible TypeScript versions.
First of all you should NOT upgrade directly over several major versions. when upgrading from Angular 5 to 7, upgrade to Angular 6 first, then to v7 (see https://angular.io/guide/releases#supported-update-paths).
It's also quite comfortable to use the CLI update feature: https://angular.io/guide/releases#supported-update-paths It takes care that all relevant packages and dependencies (e.g. correct typescript version) are installed, uninstalls angular-packages that are not used anymore (e.g. when they were incorporated in other packages) and provides information about what has to be refactored or refactors some code automatically, if possible.
In any case, it is a good idea to follow the Angular Upgrade Guide: https://update.angular.io/ It also tells you which steps you have to take and what might be required to be done manually to successfully upgrade Angular.
But concerning the concrete problem:
In the case described in the question, the Angular team probably changed how template
is handled (i.e. that it actually has to be a real string). And require("./app.component.html")
is not a string.
So @Peter Kim 's answer should have solved you problem.
I had a similar case when upgrading from Angular 7 to Angular 8: We used a correct string with a correct path for templateUrl
, but got the error
Error: The template specified for component XXX is not a string
I'm not completely sure if it was the TypeScript version or the change from commonjs
to esnext
and from "target": "es5"
to es2015
(see tsconfig.json), but my guess is the first.
When those don't match the version the Angular Compiler uses, the interpretation of strings (or their type, to be more precise) could differ. So, although the path is a correct string you can get that error.
In mycase it was a little "obvious", because although we use templateUrl
, I got the template
error, which the compiler handles first.
Upvotes: 0
Reputation: 36
If anyone still has this error then add this line in your app.component.ts
styleUrls: ['./app.component.css']
if this generates "Uncaught Error: Expected 'styles' to be an array of strings." then add following loaders hope it solves all problems
{
test: /\.html$/,
use: 'html-loader' //raw-loader
},
{
test: /\.css$/,
// include: path.join(__dirname, 'src', 'app'),
use: [
'to-string-loader', 'css-loader',
],
}
Upvotes: 2
Reputation: 1977
@Component({
selector: "app",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
You don't need to require()
a template, or templateUrl, to be more specific. Just provide the correct relative path. Note also that I'm using templateUrl
, not template
. Same goes for styleUrls
.
Upvotes: 0