angular / angular-cli

CLI tool for Angular
https://cli.angular.io
MIT License
26.76k stars 11.97k forks source link

Jade support in webpack releases #1886

Closed ShadowManu closed 7 years ago

ShadowManu commented 8 years ago

Sorry for not providing template information but I only have my phone available (and there's no critical info either).

Is there some in-the-works support for jade? The related issues/PR 's were closed but no real solution was provided. What can be done to have support for this?

ShadowManu commented 8 years ago

So you guys closed #996 and #968 in favor of #40, then closed #40 with no specific ending, then closed the efforts in #1433 and #626 because you changed to webpack and here we are with no answers.

Sorry, I'm not trying to be annoying, specially when I see a lot of hate on recent issues with bugs regarding latest TS/Angular/CLI combinations. I can understand error because we are humans, I can understand time because we need to sleep and have to live, but I do hate purposeful indifference, just because its not your problem. I'm open to work myself on the CLI on a new PR, but I do need guidance, and that really starts at least with a single answer in a timelapse of 10 days. Nevertheless, thank you for your efforts.

niklas-dahl commented 8 years ago

This is my current "solution":

gulpfile.js:

let path = require('path');
let gulp = require('gulp');
let pug  = require('gulp-pug');

let pugFiles = './src/**/*.pug';

gulp.task('compilePug', () => {
  gulp.src( pugFiles )
    .pipe( pug().on('error', () => console.log('JADE ERROR')) )
    .pipe( gulp.dest('./src') );
});

gulp.task('default', ['compilePug'], () => {
  gulp.watch(pugFiles, ['compilePug']);
});

.vscode/settings.json:

{
  "files.exclude": {
      "src/app/**/*.html": {"when": "$(basename).pug"}
  }
}

This actually works but it's obviously only a temporary solution..

ShadowManu commented 8 years ago

My team is using pug-cli with --watch at the moment for the same results. However, I would prefer jade to be part of the webpack bundling itself. I'll submit a PR if I have time to figure out how to set it up.

theklausster commented 8 years ago

Any news on how to add pug to cli?

I opened a thread on Stockoverflow aswell, hoping for some result http://stackoverflow.com/questions/39518500/how-to-add-pug-to-angular-cli

ShadowManu commented 8 years ago

Opened a PR to see how this goes.

filipesilva commented 8 years ago

Heya @ShadowManu, we're not trying to be indifferent and I'm sorry that the jade support has fallen to the wayside.

I can't say jade/pug support is a big on our radars right now to be honest. If you can get a PR to work I'm happy to review it, but bear in mind that it needs to have tests and documentation.

See https://github.com/angular/angular-cli#development-hints-for-hacking-on-angular-cli for a way to start working with a local copy of the CLI.

The command that runs the e2e suite is node tests/e2e_runner.js. Have a look at https://github.com/angular/angular-cli/tree/master/tests/e2e/tests/build/styles for sass/less/styl tests.

You should test that the the correct html is generated, and that base jade/pug functionality (like imports) works.

Regarding documentation, something akin to https://github.com/angular/angular-cli#css-preprocessor-integration should be enough.

Ideally we'd also support initializing a project with pug like we do with sass (ng new sassy-project --style=sass), or setting the default template language (ng set defaults.styleExt scss) but to be honest that's further down the road.

ShadowManu commented 8 years ago

Thanks man. I'll be looking at the tests and a proper similar documentation as soon as I have time.

jurienhamaker commented 8 years ago

Any updates @ShadowManu ?

nvrossett commented 8 years ago

@ShadowManu please, you can look too the support to (lost-grid and/or jeet.gs) and rupture in stylus too?

ShadowManu commented 8 years ago

@KingsDevelopment @filipesilva I've worked a little with some time I had on this, but got blocked on how to make the tests pass (specially on the time they take). I'll have a second try tomorrow.

@nvrossett not that I have knowledge of it. And probably should be on a different PR/issue.

qtleeq commented 7 years ago

I just wanted to throw my support behind @tycho01 's pug-plugin-ng and pug-ng-html-loader. I used them to use pug with the Angular Class seed, and it really cleans up the syntax and makes development with Angular2 and pug very pleasant. I recommend checking it out:

https://github.com/tycho01/pug-plugin-ng https://github.com/tycho01/pug-ng-html-loader

(pug-ng-html-loader is just a fork of pug-html-loader which allows pug-plugin-ng to work)

KiaraGrouwstra commented 7 years ago

@TaylorDennisLee: thanks. note that for Webpack 2 it should work without the additional loader as well now, see the readme.

Edit: note that original pug syntax is not harmed/disabled; the plugin just patches the lexer to ensure this cleaner more natural (perspective: HTML) option is parsed correctly as well.

qtleeq commented 7 years ago

@tycho01 Okay, so now pug-plugin-ng should work with pug-html-loader, as long as you are using Webpack 2?

Also, do you still have to do

template: require('./myComp.pug')

instead of:

templateUrl: 'myComp.pug'

Thanks,

Taylor

KiaraGrouwstra commented 7 years ago

@TaylorDennisLee: yeah; if you're experiencing issues feel free to file them. It does still need the require like that, though it seems angular-cli appeared to have addressed this for Sass and co., so I imagine they could for template engines like Pug as well.

ghost commented 7 years ago

@tycho01 can you please provide small guide how to add this loader to angular cli. I'm getting:

src/app/app.component.pug Unexpected token (1:3) You may need an appropriate loader to handle this file type.

import { Component } from '@angular/core';
@Component({
selector: 'app-root',
 template: require('./app.component.pug'),
 styleUrls: ['app.component.scss']
})
export class AppComponent {
  title = 'app works!';
}
KiaraGrouwstra commented 7 years ago

@mbonski: I may have use for further info (where/how you set it, first line of the pug file, whether it worked without it). Could you post an issue with those here?

ghost commented 7 years ago

@tycho01 I created one. reference

qtleeq commented 7 years ago

I'd be interested to see how to do this with just temporary script that runs right before "ng serve" or "ng build" and also what in the angular-cli source code a change would naturally go. @tycho01 do you have a link for how they handled the Sass issue?

KiaraGrouwstra commented 7 years ago

@TaylorDennisLee you might consider using a Gulp task for Pug compilation then, preferably along with one of the watchy kind. That's what I've been using, failing a better solution thus far. That could look something like this:

let gulp = require('gulp'),
    gulpWatch = require('gulp-watch'),
    runSequence = require('run-sequence'),
    pug = require('gulp-pug'),
    pug_plugin_ng = require('pug-plugin-ng');

let pug_opts = { doctype: 'html', plugins: [pug_plugin_ng], pretty: true };
let toSrc = gulp.dest((file) => file.base);

gulp.task('pug', () =>
  gulp.src('src/**/*.pug')
  .pipe(pug(pug_opts))
  .pipe(toSrc)
);

gulp.task('watch', [], () => {
  runSequence(
    ['pug'],
    () => {
      gulpWatch('src/**/*.pug', () => gulp.start('pug'));
    }
  );
});

As to changes, I linked ShadowManu's and mine in mbonski's issue thread.

On the Sass point, I didn't know yet :), but the magic appears to be located here. If I'm reading that correctly, than it should be automatically adding support for any extension already recognized by webpack. So I may have been wrong there earlier!

ShadowManu commented 7 years ago

@TaylorDennisLee @tycho01 why not simply using pug src --watch & ng serve? Sure, since they're running simultaneously, webpack generally starts doing 2 builds. But hey, config-wise, you just need to install pug and pug-cli with npm.

KiaraGrouwstra commented 7 years ago

@ShadowManu: Yeah, under normal circumstances I suppose that would've been the straight-forward way. One complication I faced personally with my plugin was (1) adding configuration, and (2) having to ensure I could add Pug plugins as well (-> functions, therefore can't survive JSON serialization, so couldn't be passed through a CLI). I never really wanted to use a plugin, but that's how it ended up. I'd definitely rather not resort to Gulp either.

I just did manage that with help from @TaylorDennisLee though, so to answer @mbonski's earlier question of a guide on how to get this to work before it's merged:

git clone -b pug https://github.com/zoitravel/angular-cli.git
# alternative with plugin: git clone -b pug-html https://github.com/tycho01/angular-cli.git
cd angular-cli
npm link
cd PATH/TO/MY/PROJECT
npm link angular-cli
# in component: templateUrl: './my_pug_file.pug',
ng serve

(Now as to the real frontier, ditching pug gulp tasks in Ionic...)

vanor89 commented 7 years ago

Has anyone gotten variable interpolation to work with webpack1 and pug-ng-html-loader? For some reason its not being able to access my variables

Edit: Just figured out I was basically writing the angular templates using pug and rendering it so instead of using pug variables I should be using angular variables like such {{var}}

CrystalzWind commented 7 years ago

I found a way to use AngularCLI with Pug using pug-html-loader. After generate new projects using ng new. Install pug and pug-html-loader packages. npm install --save-dev pug pug-html-loader. Add pug-html-loader to your project \node_modules\@angular\cli\models\webpack-configs\common.js

{ test: /.(pug|jade)$/, loader: 'pug-html-loader' }, under { test: /.html$/, loader: 'raw-loader' },

Use .jade template in component.

@Component({ selector: 'app', templateUrl: './app.template.jade' })

I'v made a demo template here https://github.com/CrystalzWind/AngularCLI-Pug *Note: We must add pug loader to common.js manually after install

donmahallem commented 7 years ago

Equivalent option to @CrystalzWind 's example is to use pug-loader with apply-loader.

npm install pug-loader apply-loader

and piping the output of the pug-loader through the apply loader which simply executes the template function.

{ test: /\.pug$/, loader: "apply-loader!pug-loader?self" } in

\node_modules@angular\cli\models\webpack-configs\common.js

Which works with ng serve and ng build --aot for me now

ScallyGames commented 7 years ago

Extending on the workaround presented by @CrystalzWind and @donmahallem, looking at https://github.com/angular/angular-cli/blob/master/packages/%40angular/cli/models/webpack-configs/common.ts#L33 https://github.com/angular/angular-cli/blob/master/packages/%40angular/cli/models/webpack-configs/common.ts#L104-L112 it seems like giving configuration access to the extraRules variable (there seems to be some configuration options through buildOptions and appConfig already) might be enough to solve this issue.

Edit: Aides359@f3cfdb803c7a17d2d18707f296e6fa51efb8a172 shows how such a change might look like (it works but I am fully aware that this is not suited for PR yet). This would allow "loaderRules": [{ "test": "\\.(pug|jade)$", "loader": "apply-loader!pug-loader" }] in .angular-cli.json to fix this issue.

filipesilva commented 7 years ago

I'm sorry to be the bearer of bad news, but jade/pug support will not make it to 1.0. It's an medium/big feature that we can't spare the time to make sure it work properly.

I know it looks like it would only be a small change in loaders but that's just not been the case with similar features like sass support.

We're looking at it for 2.0 instead, either as base functionality or as one of the main usecases for addons.

KiaraGrouwstra commented 7 years ago

Thanks for the update. If we could help out in the testing department, I'd be glad to.

ScallyGames commented 7 years ago

@filipesilva one of the things that would need some consideration for proper pug support would be how to handle the angular syntax with pug since pug has problems with it (would we want to trade equivalence to pug for syntax convenience).

For reference see tycho01/pug-plugin-ng

KiaraGrouwstra commented 7 years ago

On that, fixing Pug to play nice with Angular amounted to one small addition if it'd made it into Pug core (-> consider '[' and '(' after whitespace as valid indication a new property has started). While I feel this makes much sense in the Angular 2+ context, I don't consider it a blocker for initial support, in the sense that it's pretty much backward compatible. In the Angular context I'd be in favor of doctype: 'html' as well, to allow #myVar / md-raised-button over #myVar='' / md-raised-button=''.

filipesilva commented 7 years ago

They could, yes. We'd still like to make it a first class citizen one day.

ScallyGames commented 7 years ago

@MarkPieszak this was my current solution to this problem. Thanks for mentioning.

ausir0726 commented 7 years ago

hope some day can support pug in angular-cli

Anthonyzou commented 7 years ago

@mbonski Your example is really close. First install pug and pug-loader and use this example code.

import { Component } from '@angular/core';
@Component({
selector: 'app-root',
 template: require('pug-loader!./app.component.pug')(),
 styleUrls: ['app.component.scss']
})
export class AppComponent {
  title = 'app works!';
}

The only difference is template: require('./app.component.pug') To => template: require('pug-loader!./app.component.pug')()

You may also need to add the following into typings.d.ts

// telling the typescript compiler that there is a global function
// called require. And to not freak out about references to it.
declare var require: any;

This also works for any other loader in the webpack universe

donmahallem commented 7 years ago

So far I got it working with ng eject BUT this does not work with tests which again does desire an appropiate loader.

@Anthonyzou Your workaround does work for JIT but I don't seem to get it running with AOT. The error reads as follows:

Error encountered resolving symbol values statically. Calling function 'template', function calls are not supported. Consider replacing the function or lambda with a reference to an exported function, resolving symbol abc in a/b/c

Following the advice of the error and some sites regarding aot I tried: ` export function template() { return require("pug-loader!./test.component.pug")(); }

@Component({ template: template() })`

But it still errors with basicly the same message. Any ideas?

Anthonyzou commented 7 years ago

@donmahallem I actually have no idea, actually. This is adapted from a graphql angular2 example where they manually require a graphql file and it works with AOT. It must also depend on how the loader is built.

filipesilva commented 7 years ago

Heya all, this isn't a feature that we're looking at adding in the 1.x timeframe, but rather something that would happen as a third party addon using the upcoming addon system for v2+.

svallory commented 7 years ago

Guys, I made a pull request to allow tweaking webpack config with a file in the project root. For now, you can use the cli at https://github.com/cashfarm/angular-advanced-cli (branch 1.2.x)

Install pug, pug-ng-html-loader and add a webpack.config.js with this to root of your project:

module.exports = {
  module: {
    rules: [
      {
        test: /\.(pug|jade)$/,
        use: ['pug-ng-html-loader']
      }
    ]
  }
}

Then your components can use pug

@Component({
  selector: 'app-root',
  templateUrl: './app.component.pug',
  styleUrls: ['./app.component.styl']
})

But your index has to stay in html.

pexak commented 7 years ago

Any update?

MarkPieszak commented 7 years ago

Going along with some of the recommendations above, I created a little script that can be ran to automatically insert the pug rule into the node_modules folder. @Pexak

This can be used as a temporary solution until it can be available natively. Note this could need to be updated & changed if the CLI changes the location or formatting of this file. It's naively searching for rules: [ within this specific file.

npm i --D apply-loader pug-loader

pug-rule-insert.js

Now you can just create a simple js file with the code below (put it at your root project level).

const fs = require('fs');

const commonCliConfig = 'node_modules/@angular/cli/models/webpack-configs/common.js';
const pug_rule = `\n{ test: /\.pug$/, loader: "apply-loader!pug-loader?self" },`;

fs.readFile(commonCliConfig, (err, data) => {
  if (err) { throw err; }

  const configText = data.toString();

  if (configText.indexOf(pug_rule) > -1) {
    return;
  }

  console.log('-- Inserting .pug webpack rule -- ');

  const position = configText.indexOf('rules: [') + 8;
  const output = [configText.slice(0, position), pug_rule, configText.slice(position)].join('');

  const file = fs.openSync(commonCliConfig, 'r+');
  fs.writeFile(file, output);
  fs.close(file);
});

Running it

Run it simply with: node pug-rule-insert.js or create a nice postinstall hook to do it for you on new installs.

"postinstall": "node pug-rule-insert.js"

Needed this for a client, hope this helps!

Works with ng serve (even live reloads pug file changes) and AoT ng prod builds, even Universal + CLI projects! 🎁

clovisj commented 7 years ago

Tnks @MarkPieszak

chenzhiguang commented 6 years ago

@MarkPieszak thank you. I used pug-html-loader and html-loader instead, it is working fine, including the include ./pug-file

const pug_rule = `\n{ test: /.pug$/, loader: [ 'html-loader', { loader: "pug-html-loader", options: { doctype: 'html', pretty: true } } ], },`;

oguimbal commented 6 years ago

@MarkPieszak @clovisj @chenzhiguang [Warning] this trick works fine, as long as you do not name your template files something.TS.pug (which I used to do so they pop below their .ts counterpart in vscode)

If you do so, your AOT builds will fail silently (at least on my machine, as of today)

This one was f***ng hard to find. see #8904

angular-automatic-lock-bot[bot] commented 5 years ago

This issue has been automatically locked due to inactivity. Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.