thelarkinn / angular2-template-loader Goto Github PK
View Code? Open in Web Editor NEWChain-to loader for webpack that inlines all html and style's in angular2 components.
License: MIT License
Chain-to loader for webpack that inlines all html and style's in angular2 components.
License: MIT License
Hi
I am using this loader to load styles to my application and it really sucks that I need to change my webpack config for css files from "css" to "to-string!css" because I need to use styles elsewhere in my app and I don't want them to be strings. Basically I am stuck with only "css" loader for my app to work. My question is shouldn't this loader convert css into strings internally? Because its only job is to take css(and html) and load it as a string to the component.
0.6.1 version doesn't recognize some of my relative paths.
This component
@Component({
selector: 'home',
templateUrl: 'home.component.html'
})
export class HomeComponent ...
builds to
HomeComponent = __decorate([
core_1.Component({
selector: 'home',
templateUrl: 'home.component.html'
}),
__metadata("design:paramtypes", [router_1.ActivatedRoute])
], HomeComponent);
Looks like loader doesn't recognize templateUrl path.
When I roll back to 0.6.0 it works fine.
Hi,
I'm having trouble making it work with awesome-typescript-loader.
I'm currently using the latest versions of all modules as follow :
"devDependencies": {
"angular2-template-loader": "^0.5.0",
"awesome-typescript-loader": "^2.2.4",
"typescript": "^2.0.3",
"webpack": "^2.1.0-beta.25"
}
But I tried some others versions combinations and still couldn't make it work.
It works with ts-loader
or if you set the component as the main entry on webpack (totally useless but might help to find out what's going on).
I've created a minimal project to demonstrate, if you need more information about source code or tsconfig you can check it directly on the repo.
Hi,
In my code I'm currently dynamically creating component metadata and it's being replaced.
A more restrictive regex would avoid that.
/templateUrl\s*:\s*(['"`].*['"`])/g
/styleUrls\s*:(\s*\[.*['"`]+.*\])/g
Theses would be enough for me.
Introducing quote allows it to differentiate when we are using programmatic code like referencing to a variable and when we are statically setting an url through a string.
But maybe including '.html' or even checking for a preceding @component may be even better. Dunno if it's worth the trouble.
Do you have some plans to add the styles and script config by default.
What I mean: Often I have something like this
my.component.ts
my.component.html
my.component.scss
It is obvious when you see the naming that these files belong together. There should be a convention model for angular which integrates the content automatically.
EDIT (Nov 1, 2016):
template: require('./myComponent.html') was necessary for me to use with awesome-typescript-loader, which defeated the point since templateURL should be working and converted to in-line on the fly. templateUrl didn't work even with a hardcoded path. However no issues with ts-loader so my problem was solved.
Here is some of my webpack.test.js configuration:
module: {
loaders: [
{
test: /\.ts$/,
loaders: ['awesome-typescript-loader', 'angular2-template-loader']
},
{
test: /\.html$/,
loader: 'raw-loader'
}
]
}
In the following legitimate code snippet:
@Component({
selector: "my-app",
templateUrl: './app.component.html'
//styleUrls: ["app.component.css"]
})
or this:
@Component({
selector: "my-app",
templateUrl: './app.component.html' //Very important comment
})
the regular expression templateUrlRegex
in index.js fails to capture, leaving the URL in the file to be treated as a separate html.
I installed angular2-template-loader into my project with the usual:
npm install angular2-template-loader --save-dev
Looking in node_modules/angular2-template-loader
directory I can see that the package.json
has v0.6.0, however, the index.js
file is the older version (without the keepUrl feature). I also noticed that the v0.6.0 tag on the project also references the older index.js
.
As a workaround, I'm getting the package from github instead of NPM:
devDependencies {
"angular2-template-loader": "TheLarkInn/angular2-template-loader"
...
}
Please, observe the following TypeScript file:
import { Component } from "@angular/core";
@Component({
selector: 'app-root',
templateUrl: './app/app.component.html'
})
export class AppComponent {
}
And it works fine before I use angular2-template-loader. When I am trying to use the latter and run webpack it fails with the following message:
polyfills.js 283 kB 1 [emitted] polyfills
vendor.js 3.32 MB 2 [emitted] vendor
main.js.map 17.2 kB 0 [emitted] main
polyfills.js.map 353 kB 1 [emitted] polyfills
vendor.js.map 3.94 MB 2 [emitted] vendor
index.html 607 bytes [emitted]
+ 912 hidden modules
ERROR in ./src/client/app/app.component.ts
Module not found: Error: Cannot resolve 'file' or 'directory' ./app/app.component.html in C:\Users\markk\IdeaProjects\QuestionarySample2\src\client\app
@ ./src/client/app/app.component.ts 18:22-57
...
Child html-webpack-plugin for "index.html":
+ 1 hidden modules
C:\Users\markk\IdeaProjects\QuestionarySample2>
(there are more errors like that for other components, I replaced them with an ellipsis)
The loader converts the aforementioned source into:
import { Component } from "@angular/core";
@Component({
selector: 'app-root',
template: require('./app/app.component.html')
})
export class AppComponent {
}
And now it fails.
As I understand, the reason is that require works off the current directory, whereas the templateUrl is relative to the root. So, './app/app.component.html' is correct when taken relative to the root, but wrong when relative to the current location.
It is worth noting, that I do not use require anywhere in the source code, only the ES6 import statement, which is also relative to the current location. It is only the Angular2 templateUrl and styleUrls that are relative to the root.
Anyway, I must be doing something wrong, because nobody seems to have my problem. But what am I doing wrong?
The file name is src/client/app/app.component.ts. The source code directory structure is:
C:.
│ .gitignore
│ karma.conf.js
│ package.json
│ tsconfig.json
│ tslint.json
│ typings.json
│ webpack.config.js
│
├───config
│ karma-test-shim.js
│ karma.conf.js
│ webpack.common.js
│ webpack.dev.js
│ webpack.prod.js
│ webpack.scratch.js
│ webpack.test.js
│
└───src
├───client
│ │ global.css
│ │ index.html
│ │ main.ts
│ │ polyfills.ts
│ │ tsconfig.json
│ │ vendor.ts
│ │
│ └───app
│ │ app.component.html
│ │ app.component.ts
│ │ app.module.ts
│ │ app.routing.ts
│ │ settings.component.ts
│ │ signout.component.ts
│ │
│ ├───assets
│ │ ...
│ │
│ ├───questionnaire
│ │ ...
│ │
│ └───shared
│ ...
│
└───server
api.ts
main.ts
tsconfig.json
The webpack configuration is:
webpack.config.js
module.exports = require('./config/webpack.dev.js');
./config/webpack.dev.js
var webpackMerge = require('webpack-merge');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var commonConfig = require('./webpack.common.js');
const path = require('path');
module.exports = webpackMerge(commonConfig, {
// devtool: 'cheap-module-eval-source-map',
devtool: 'source-map',
output: {
publicPath: `http://localhost:${commonConfig.port}/`,
filename: '[name].js',
sourceMapFilename: '[name].js.map',
chunkFilename: '[id].chunk.js'
},
plugins: [
new ExtractTextPlugin('[name].css')
],
devServer: {
inline: true,
hot: true,
progress: true,
port: commonConfig.port,
proxy: {
'/api*': {
target: `http://localhost:${commonConfig.port - 1}`
}
},
historyApiFallback: true,
watchOptions: {
aggregateTimeout: 300,
poll: 1000
}
}
});
./config/webpack.common.js
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
const path = require('path');
module.exports = {
port: process.env.PORT || 3000,
entry: {
polyfills: './src/client/polyfills',
vendor: './src/client/vendor',
main: './src/client/main'
},
output: {
path: path.join(__dirname, '../dist/client'),
},
resolve: {
extensions: ['', '.js', '.ts']
},
module: {
loaders: [
{
test: /\.ts$/,
loaders: ['ts', 'angular2-template-loader']
},
{
test: /\.html$/,
// loader: 'html'
loader: 'raw'
},
{
test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/,
loader: 'file?name=assets/[name].[hash].[ext]'
},
// {
// test: /\.css$/,
// exclude: path.join(__dirname, '../src/client/app'),
// loader: ExtractTextPlugin.extract('style', 'css?sourceMap')
// },
{
test: /\.css$/,
// exclude: path.join(__dirname, '../src/client/app'),
loader: 'raw'
}
]
},
plugins: [
new webpack.optimize.CommonsChunkPlugin({
name: ['main', 'vendor', 'polyfills']
}),
new HtmlWebpackPlugin({
template: 'src/client/index.html'
})
]
};
Including a space after templateUrl
, e.g. templateUrl : './home.template.html'
instead of templateUrl: './home.template.html'
causes the router to throw Failed to load about.template.html
at runtime.
Obviously this can be worked around, but a coworker who prefers spaces after his properties was about ready to flip his keyboard today when trying to load a template, and this could be a gotcha for other developers unaware of this restriction.
For the offline compiler to work, we want to instead of having require('./path')
instead have the template resolved through the loader chain, the output of the template will be the actually source.
this.resolve
I've got a strange behavior while loading the component template, some components works fine by using relative paths:
templateUrl: './home.component.html'
And others cannot work without specifying an absolute path:
templateUrl : '/src/app/shared/components/menu/menu.component.html'
However, they are in the same folder!
I got this error in the console:
GET http://localhost:7000/menu.component.html 404 (Not Found)
scheduleTask @ zone.js?fad3:1645
ZoneDelegate.scheduleTask @ zone.js?fad3:255
Zone.scheduleMacroTask @ zone.js?fad3:168
(anonymous) @ zone.js?fad3:1669
send @ VM11106:3
ResourceLoaderImpl.get @ platform-browser-dynamic.umd.js?04e2:55
DirectiveNormalizer._fetch @ compiler.umd.js?9df7:13541
DirectiveNormalizer.normalizeTemplateAsync @ compiler.umd.js?9df7:13587
DirectiveNormalizer.normalizeTemplate @ compiler.umd.js?9df7:13559
CompileMetadataResolver._loadDirectiveMetadata @ compiler.umd.js?9df7:17874
(anonymous) @ compiler.umd.js?9df7:18050
CompileMetadataResolver.loadNgModuleDirectiveAndPipeMetadata @ compiler.umd.js?9df7:18049
(anonymous) @ compiler.umd.js?9df7:27290
JitCompiler._loadModules @ compiler.umd.js?9df7:27289
JitCompiler._compileModuleAndComponents @ compiler.umd.js?9df7:27244
JitCompiler.compileModuleAsync @ compiler.umd.js?9df7:27210
PlatformRef_._bootstrapModuleWithZone @ core.umd.js?e2a5:8476
PlatformRef_.bootstrapModule @ core.umd.js?e2a5:8451
(anonymous) @ main.ts?7d64:7
(anonymous) @ main.ts?7d64:7
76 @ app.js:15
__webpack_require__ @ polyfills.js:51
0 @ app.js:7
__webpack_require__ @ polyfills.js:51
webpackJsonpCallback @ polyfills.js:22
(anonymous) @ app.js:1
zone.js?fad3:405 Unhandled Promise rejection: Failed to load menu.component.html ;
I'm using the latest version of everything!, So do you have explanation for this ?
JSON names are supposed to be double-quoted according to the standard, however angular2-template-loader does not work. The templateUrl and styleUrls fields from the following Component directive aren't recognized:
@Component({
"selector": "my-app",
"styleUrls": [ "./my-app.component.ts.scss" ],
"templateUrl": "./my-app.component.ts.html",
"encapsulation": ViewEncapsulation.None
})
However, after removing the double-quotes from the directive, the loader finds the fields correctly:
@Component({
selector: "my-app",
styleUrls: [ "./my-app.component.ts.scss" ],
templateUrl: "./my-app.component.ts.html",
encapsulation: ViewEncapsulation.None
})
This is technically invalid JSON as the standard requires that object keys be strings (double-quoted tokens). I prefer to use syntactically correct JSON in my code to maximize the interoperability in browsers, and I don't like having to dumb it down just because lazily ignoring the standards is pervasive among web developers.
To fix the problem, you should just have to add a quote-balancing group to your regex.
FWIW: The official ECMA standard for JSON declares that object keys are strings, which it defines as tokens wrapped in quotes.
Seeing that the last active issue is from late September.
Hello sir, I have seen that problem in #21 and #20, to deal with it, can you make an option to decide the path is either absolute or relative? For example:
function replaceStringsWithRequires(string, option) { return string.replace(stringRegex, function (match, quote, url) { if (url.charAt(0) !== "." && !option) { url = "./" + url; } return "require('" + url + "')"; }); }
Example :
templateUrl : './sometemplate.component.html' <- not good
templateUrl: './sometemplate.component.html' <- good
I'll take a look at the project this week to see what the regex is doing to cause it.
AS titled
I'm having trouble understanding your documentation. The code snippet given is
@Component({
selector: 'awesome-button',
template: require('./button.template.html'),
styles: [require('./button.style.css')]
})
export class AwesomeButtonComponent { }
But then right below that it says
The angular2-template-loader searches for templateUrl and styleUrls declarations inside of the Angular 2 Component metadata and replaces the paths with the corresponding require statement
So why does the example use template
and styles
? What am I not getting here?
function replaceStringsWithRequires(string) {
return string.replace(stringRegex, function (match, quote, url) {
/* add webpack resolve root support
if (url.charAt(0) === "/") {
url = url.substring(1);
}else */if (url.charAt(0) !== ".") {
url = "./" + url;
}
return "require('" + url + "')";
});
}
A few days ago, raw-loader v2.0.0 was published. This release changed to use ES Module exports instead of CommonJS exports (webpack-contrib/raw-loader#69). I believe this has caused angular2-template-loader
to no longer work.
Everything compiles fine, but when you run the Angular application, you get the error:
Error: Expected 'styles' to be an array of strings.
I think this is because this loader is using require(...)
, but that's now returning an object with a default
property that contains a string, rather than just returning a string. I haven't confirmed that though. I wanted to submit this issue while it was still fresh in my mind. When I get some time later on, I'll create a simple repro and investigate a bit further.
Current Workarounds:
raw-loader
to 1.0.0
.ERROR in ./src/app/app.component.ts
Module not found: Error: Cannot resolve 'file' or 'directory' ./app.component.css in C:\Github\Data-Platform\src\DataPlatform\src\app @ ./src/app/app.component.ts 27:21-51
How do I remedy this? Do I have to precompile the sass into css before this somehow?
I am currently developing an Angular 2 project (Let's call it Workbench) which dependes on another Angular 2 project (Let's call it Panel).
Panel provides of a lot of components which are then used in Workbench.
At the same time I am developing Workbench, I make changes to Panel, so I need to view the changes immediately and that's why I linked the dependency with npm link (
npm link ../panel/dist
) and after that Panel is being found by my bundler (Webpack 2) and its bundled correctly.
Until here everything works fine, the problem comes when the browser loads the Workbench app because it doesn't find the templates of the components provided by the Panel component, it throws a 404 - Error Message
.
Here's a screenshot of the error messages:
As you can see, the angular2-template-loader
is trying to resolve the templates by going to the src folder of the Workbench app, not the panel app. (http://127.0.0.1:8080/src/header.component.html
)
Here's how I import the templates and styles of the components of Panel.
@Component( {
selector: "cp-header",
templateUrl: "./header.component.html",
styleUrls: [ "./header.component.scss" ],
host: {
class: "ui navigation inverted menu"
}
} )
And these are the Webpack rules for resolving file extensions:
module: {
rules: [
{
test: /\.ts$/,
use: [ "awesome-typescript-loader", "angular2-template-loader", "angular-router-loader" ]
},
{
test: /\.json$/,
use: "json-loader"
},
{
test: /\.html$/,
use: "raw-loader"
},
{
test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/,
use: "file-loader?name=assets/[name].[hash].[ext]"
},
{
test: /\.css$/,
use: [ "style-loader", "css-loader" ],
include: [ helpers.root( "src", "styles" ) ]
},
{
test: /\.scss$/,
exclude: /node_modules/,
use: [ "raw-loader", "sass-loader" ],
// use: [ "style-loader", "css-loader", "sass-loader" ],
},
]
},
Is it possible to have linked packages using angular2-template-loader
?
Loader needs sourcemaps support. As well as calling this.cacheable()
Since the template loader replaces strings with requires()
if users are using typescript module: es2015
, they will get typing errors for require. We should probably mention that an ambient typing is needed, if one doesn't already exist in README instructions.
Hi,
I've experienced that instead of proper file requiring, the file content passes into its URL :-(
GET http://localhost:8080/%3C!--The%20content%20below%20is%20only%20a%20placeholder%20and%20can%20be%20replaced.--%3E%0A%3Cdiv%20style=%22text-align:center%22%3E%0A%20%20%3Ch1%3E%0A%20%20%20%20Welcome%20to%20%7B%7B%20title%20%7D%7D!%0A%20%20%3C/h1%3E%0A%3C/div%3E%0A%3Ch2%3EHere%20are%20some%20links%20to%20help%20you%20start:%20%3C/h2%3E%0A%3Cul%3E%0A%20%20%3Cli%3E%0A%20%20%20%20%3Ch2%3E%3Ca%20target=%22_blank%22%20rel=%22noopener%22%20href=%22https:/angular.io/tutorial%22%3ETour%20of%20Heroes%3C/a%3E%3C/h2%3E%0A%20%20%3C/li%3E%0A%20%20%3Cli%3E%0A%20%20%20%20%3Ch2%3E%3Ca%20target=%22_blank%22%20rel=%22noopener%22%20href=%22https:/github.com/angular/angular-cli/wiki%22%3ECLI%20Documentation%3C/a%3E%3C/h2%3E%0A%20%20%3C/li%3E%0A%20%20%3Cli%3E%0A%20%20%20%20%3Ch2%3E%3Ca%20target=%22_blank%22%20rel=%22noopener%22%20href=%22https:/blog.angular.io/%22%3EAngular%20blog%3C/a%3E%3C/h2%3E%0A%20%20%3C/li%3E%0A%3C/ul%3E%0A%0A 404 (Not Found)
...
{
test: /\.ts$/,
use: ['awesome-typescript-loader', 'angular2-template-loader?keepUrl=true',],
exclude: [/node_modules/, /\.(spec|e2e)\.ts$/]
},
...
"angular2-template-loader": "^0.6.2",
"awesome-typescript-loader": "^3.4.1",
"webpack": "^3.10.0",
"webpack-dev-middleware": "^1.12.2",
"webpack-dev-server": "^2.9.7"
Any ideas?
I'm trying to apply postcss plugins to the css files specified in my my styleUrl's via postcss-loader. Their project has the following example for webpack2 config:
{
test: /\.css$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: { importLoaders: 1 }
},
{
loader: 'postcss-loader',
options: {
plugins: function () {
return [
require('precss'),
require('autoprefixer')
];
}
}
}
]
}
My understanding of angular2-template-loader is that it basically turns styleUrls: ['some-file.css']
into styles: require('some.file.css')
, which ultimately gets handled by some css loader.
Is that correct? The reason I'm questioning this is :
style-loader
with css-to-string
loader in the config pasted above, but it doesn't seem to work (doesn't autoprefix the css)."The generated require statements", (for templateUrl and styleUrls), "will be handled by the given loader for .html and .js files"
. I would expect that to say "for .html and .css files". Does this mean that the styleUrl generates some sort of .js file which isn't handled by a .css loader?I asked about the setup on the postcss-loader repo (webpack-contrib/postcss-loader#113) but they were understandably unfamiliar with this particular loader and how it should integrate with other loaders. Is there anything obviously wrong with my approach or understanding of how this loader works? Thanks!
For use webpack APIs (like require.context()
), webpack-env.d.ts is needed.
The definition includes its own require
.
https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/webpack/webpack-env.d.ts#L21
It returns a value as T
. so require()
returns the type {}
.
error TS2345: Argument of type '{ selector: string; template: {}; }' is not assignable to parameter of type 'ComponentMetadataType'.
Types of property 'template' are incompatible.
Type '{}' is not assignable to type 'string'.
idea
Maybe, The loader should replace templateUrl
to <string>require(...)
.
Hi,
Could you rename this plugin to be angular compliant?
For example: ngx-template-loader?
Thanks,
By the way, amazing job on that plugin! Thanks for the help it brings to the typescript devs out there!
In order to make sure my unit tests in typescript and Angular2 work, I had to add this snippet to my tsconfig.js
"awesomeTypescriptLoaderOptions": {
"useWebpackText": true
// Allows other loaders to be chained to awesome-typescript-loader.
},
Shouldn't there be some sort of warning mentionning that it's required when you use it wih the awesome-typescript-loader ? Probably lost 4/5 hours trying to fetch that.
Let me know what you think
E
How would you add angular2-template-loader in a angular-cli project version 1.0.0-beta.28.3?
Just testet it with the offical ts-loader and it works perfectly, cause ts-loader has the text-pipe activated by default!
Please mention this, in your README ...
BTW: Great Work :)
When I add this module the following code stop working and breaks with an error. No matter what I try to set, styleUrls: ["src/app.scss"] I can't get things to work?
@Component({ selector: "App", template: "<h1>{{msg}}</h1>", styleUrls: ["src/app.scss"] }) export class AppComponent { msg: string = "Welcome to Angular 2"; }
Hi,
if I try to do something like
styleUrls: [
'./index.css',
'materialize-css/dist/css/materialize.css'
]
it gets turned into:
styles: [
require('./index.css'),
require('./materialize-css/dist/css/materialize.css'
]
I could just use a relative path, or import 'materialize-css/dist/css/materialize.css
but I'd rather use the styleUrls option if I could. Do you know how I could accomplish this?
[x] bug report
[ ] feature request
[ ] support request
Current behavior
Given the following webpack configuration:
exports.typescriptModule = function() {
return {
test: /\.ts$/,
loaders: ['ts', 'angular2-template-loader']
}
};
{
test: /\.scss$/,
include: helpers.root('src'),
loaders: ['raw', 'sass']
}
And this component:
import { Component } from '@angular/core';
import { ROUTER_DIRECTIVES } from '@angular/router';
import '../../public/css/styles.scss';
@Component({
selector: 'my-app',
templateUrl: './app.html',
styleUrls: ['./app.scss'],
directives: [ROUTER_DIRECTIVES]
})
export class AppComponent { }
Note that templateUrl and styleUrls is used.
When sourcemaps are created it shows the following sourcemap:
import { Component } from '@angular/core';
import { ROUTER_DIRECTIVES } from '@angular/router';
import '../../public/css/styles.scss';
@Component({
selector: 'my-app',
template: require('./app.html'),
styles: [require('./app.scss')],
directives: [ROUTER_DIRECTIVES]
})
export class AppComponent { }
/** WEBPACK FOOTER **
** ./~/angular2-template-loader!./src/app/app.ts
**/
Note the sourcemap shows template and styles with their require calls, instead of the original source.
Expected/desired behavior
Sourcemap should contain the original typescript code.
(node:6856) DeprecationWarning: loaderUtils.parseQuery() received a non-string value which can be problematic, see https://github.com/webpack/loader-utils/issues/56
parseQuery() will be replaced with getOptions() in the next major version of loader-utils.
at Object.parseQuery (c:\Dev\sso\frontend.admin\node_modules\loader-utils\index.js:78:3)
at Object.module.exports (c:\Dev\sso\frontend.admin\node_modules\angular2-template-loader\index.js:21:27)
In Example Markup section, text says "Here is an example markup of the webpack.config.js, which chains the angular2-template-loader to the tsloader", but then following code block only uses angular2-template-loader.
HTH
Hi there
I tried, by searching around, if there was already a similar issue/thread/question, but it seems not. I also checked for similar spec files in angular2-webpack-starter, but strangely enough none of those was showing the present use case, so maybe it's something known and someone is already working at it. Here's the issue:
a simple AppComponent like those found in quickstart or tour of heroes has an inline template
and then style is pointed to like styleUrls: ['./app.component.css'],
. When running a smoke test spec, as soon as we try to configure testing module with component as a declaration, test fails because it fails to load CSS file (full stacktrace is appended below, at the end):
Failed: Uncaught (in promise): Failed to load app.component.css
resolvePromise@webpack:////path/to/proj/~/zone.js/dist/zone.js:418:0 <- /path/to/proj/src/client/karma-entry.js:11799:76
If instead style is manually require
d as in styles: [require('./app.component.css')],
the error goes away. This led me here on angular2-template-loader to ask whether it's a known issue or more likely there's something wrong with our setup.
Environment details and code samples follow:
// src/client/app/app.component.ts
@Component({
selector: 'my-app',
template: `
<h1>{{title}}</h1>
<nav>
<a routerLink="/dashboard">Dashboard</a>
<a routerLink="/heroes">Heroes</a>
</nav>
<router-outlet></router-outlet>
`,
styleUrls: ['./app.component.css'], // this fails
//styles: [require('./app.component.css')], // this does not fail
})
export class AppComponent {
title = 'Tour of Heroes';
}
// src/client/app/app.component-decl.spec.ts
describe('AppComponent as declaration', () => {
beforeEach(async(() => {
// refine the test module by declaring the test component
TestBed.configureTestingModule({
declarations: [ AppComponent ],
});
TestBed.compileComponents();
}));
it('should complete beforeEach', () => expect(true).toBe(true));
});
Besides, as a reference:
Test output full stacktrace:
Failed: Uncaught (in promise): Failed to load app.component.css
resolvePromise@webpack:////path/to/proj/~/zone.js/dist/zone.js:418:0 <- /path/to/proj/src/client/karma-entry.js:11799:76
resolvePromise@webpack:////path/to/proj/~/zone.js/dist/zone.js:403:0 <- /path/to/proj/src/client/karma-entry.js:11784:32
webpack:////path/to/proj/~/zone.js/dist/zone.js:451:0 <- /path/to/proj/src/client/karma-entry.js:11832:32
invokeTask@webpack:////path/to/proj/~/zone.js/dist/zone.js:225:0 <- /path/to/proj/src/client/karma-entry.js:11606:43
onInvokeTask@webpack:////path/to/proj/~/zone.js/dist/proxy.js:84:0 <- /path/to/proj/src/client/karma-entry.js:13267:54
invokeTask@webpack:////path/to/proj/~/zone.js/dist/zone.js:224:0 <- /path/to/proj/src/client/karma-entry.js:11605:55
runTask@webpack:////path/to/proj/~/zone.js/dist/zone.js:125:0 <- /path/to/proj/src/client/karma-entry.js:11506:58
drainMicroTaskQueue@webpack:////path/to/proj/~/zone.js/dist/zone.js:357:0 <- /path/to/proj/src/client/karma-entry.js:11738:43
run@webpack:////path/to/proj/~/core-js/modules/es6.promise.js:87:0 <- /path/to/proj/src/client/karma-entry.js:4074:30
webpack:////path/to/proj/~/core-js/modules/es6.promise.js:100:0 <- /path/to/proj/src/client/karma-entry.js:4087:32
flush@webpack:////path/to/proj/~/core-js/modules/_microtask.js:18:0 <- /path/to/proj/src/client/karma-entry.js:4442:12
EDIT
Further detail: all is fine at build-time and runtime for development build (e.g. not in test, but just running web app locally). One difference between development and test configurations is that webpack cache is enabled in development build, disabled in test.
Hey @TheLarkInn, quick question for you, we're developing a component library with angular 2 that is then consumed by angular 2 applications.
Is angular2-template-loader capable of digging into the component files of such a library and swapping out its templateUrls and styleUrls just as it does the consuming application, provided everything's getting pulled in by webpack (which it is)?
Let me know if I can clarify my question for you.
Thanks.
when you use ES6 quotation marks like
templateUrl: `./app.component.html`
this will render just "./app.component.html" in your app
Only the following quotation marks are working at the Moment.
templateUrl: './app.component.html'
templateUrl: "./app.component.html"
var templateUrlRegex = /templateUrl\s*:(\s*['"
](.*?)['"]\s*([,}]))/gm;
Only finds templateUrls that end with commas, suggesting two things:
That in cases where styleUrls are listed before templateUrls, and templateUrls are the last line of the component metadata, the templateUrl will not match the regex pattern (https://regex101.com/r/PylCUU/2):
styleUrls: [..],
templateUrl: '...'
And that components with only selectors and templateUrls (namely, no stylesheet), will not match the pattern (https://regex101.com/r/hyzIvz/1) either:
templateUrl: '...'
Which boils down to essentially the same issue regarding the comma that is required for a templateUrl to be matched, and two scenarios in which that might happen.
I know convention is to have templateUrls before styleUrls, but I don't think it's a hard and fast rule. And while I don't personally subscribe to styleUrls before templateUrls, I feel as though the requirement of a comma is overly strict, and the failure to inline those cases goes pretty quietly, leaving people unwilling or unequipped to dig into why this is happening at a loss to solve the problem.
Any chance we can loosen the regex on this pattern? I'd be happy to contribute the change.
50% 2/3 build modulesModuleParseError: Module parse failed: /home/dmitriy/projects/angular-quickstart/node_modules/angular2-template-loader/index.js!/home/dmitriy/projects/angular-quickstart/src/app/app.component.ts Unexpected character '@' (5:0)
You may need an appropriate loader to handle this file type.
SyntaxError: Unexpected character '@' (5:0)
Here's the file that I'm trying to process:
import { Component } from '@angular/core';
import '../../public/css/styles.css';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent { }
webpack.config :
module.exports = {
entry: {
'polyfills': './src/polyfills.ts',
'vendor': './src/vendor.ts',
'app': './src/app/app.component.ts'
},
resolve: {
root: helpers.root('src'),
extensions: ['', '.js', '.ts']
},
module: {
loaders: [
{
test: /\.ts$/,
loader: 'angular2-template-loader'
},
{
test: /\.html$/,
loader: 'html'
},
{
test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/,
loader: 'file?name=assets/[name].[hash].[ext]'
},
{
test: /\.css$/,
exclude: helpers.root('src', 'app'),
loader: ExtractTextPlugin.extract('style', 'css?sourceMap')
},
{
test: /\.css$/,
include: helpers.root('src', 'app'),
loader: 'raw'
}
]
},
plugins: [
new webpack.optimize.CommonsChunkPlugin({
name: ['app', 'vendor', 'polyfills']
}),
new HtmlWebpackPlugin({
template: 'src/index.html'
})
]
};
Just installed loader in one of our team project, and noticed [email protected] as a sub-dependency. Just wondering if installed package can be slimmed down.
Thanks.
The following works fine in 0.6.0 but fails with 0.6.2:
@Component({
selector: "app",
templateUrl: "./app.html"
})
/*
* Comment
*/
export class App {
}
Exception: Call to Node module failed with error: Error: No ResourceLoader implementation has been provided. Can't read the url "app.html"
Usually the webpack.config.js already contains some rules for loading .html or .css files. angular2-template-loader requires a webpack config that either returns .html/.css urls as string or as absolute url.
It would be nice to be able to keep the webpack config as it is and pass a prefix string to angular2-template-loader, for example "!to-string-loader!raw-loader!" so that ./test.html becomes require('!to-string-loader!raw-loader!./test.html')
Hey @TheLarkInn, trying to make a core component library in angular 2 that I can then bundle with webpack + awesome-typescript-loader + angular2-template-loader.
Because I'll be using this library in other angular2 projects, I need d.ts files, but for some reason, if I set declaration: true
, angular2-template-loader stops doing its thing and my bundle keeps its templateUrls.
I've set useWebpackText: true
.
Please update to latest version of loader-utils, currently angular2-template-loader is using [email protected], which doesnt seem to be compatible with some of the other plugins which are using latest version of loader-utils. For example angular-router-loader
From the latest few patch releases, it is becoming apparent that we should probably leverage AST parsing over Regex to provide these replacements.
Since I am 200% overbooked myself, I can't work on this myself atm. I would love for someone to take on this task. The existing tests should still be valid for passing, and maybe even a few more could be added.
Thank you everyone for contributing to issues and enhancements.
Hi,
It bit strange, in the same project, it has two different behavior.
templateUrls and styleUrls of couple of component left as URL not replaced with webpack., it works for rest of the component in the same project,
Eg, not working:
webpack_require.i(WEBPACK_IMPORTED_MODULE_1__angular_core["Component"])({
selector: 'barcode',
providers: [WEBPACK_IMPORTED_MODULE_5__Services_Order_OrderService["a" /* OrderService /], WEBPACK_IMPORTED_MODULE_6__login_UserService["a" / UserService /], WEBPACK_IMPORTED_MODULE_7__xxxxxx_services_Shared_SharedService["a" / SharedService */]],
templateUrl: '../../Views/Order/Barcode.html',
styleUrls: ['../../shared/css/xxxx/OrderEntry.css', '../../shared/css/xxxx/MainPage.css', '../../shared/css/xxxx/Common.css']
}),
Eg. of working:
webpack_require.i(WEBPACK_IMPORTED_MODULE_1__angular_core["Component"])({
selector: 'orderdetail',
providers: [WEBPACK_IMPORTED_MODULE_10__Services_Order_OrderService["a" /* OrderService /], WEBPACK_IMPORTED_MODULE_11__Services_MasterData_ClinicianService["a" / CliniciansService /], WEBPACK_IMPORTED_MODULE_12__Services_MasterData_LocationDefinitionService["a" / LocationDefinitionService /], WEBPACK_IMPORTED_MODULE_13__Services_xxxxxx_ProfileDefinitionService["a" / ProfileDefinitionService /], WEBPACK_IMPORTED_MODULE_14__Services_Shared_SharedMService["a" / SharedMService /], WEBPACK_IMPORTED_MODULE_9__shared_Services_CommonService["a" / CommonService /], WEBPACK_IMPORTED_MODULE_15__Services_Shared_SharedService["a" / SharedService /], WEBPACK_IMPORTED_MODULE_20__Components_Order_BarcodeComponent["a" / Barcode /], WEBPACK_IMPORTED_MODULE_16__Services_Patient_xxxxxService["a" / xxxxService */]],
template: webpack_require(502),
styles: [webpack_require(40)]
})
Not sure, what Am I missing? Any help would be appreciated.
Best Regards,
Munavar Hussain
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.