Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to configure raw-loader in Angular 7 to load text files?

I want to use a raw-loader with my Angular 7 to import text files into my TypeScript source code. I've found plenty of information on the subject and spent a few hours trying to get it to work, but I can not get it to work.

I start by creating a new project

ng new example --defaults --minimal

I create a text file at /src/app/example.txt with the message "Hello World"

I then modify the app.component.ts file to import this text file.

import {Component} from '@angular/core';
import str from 'example.txt';

alert(str);

@Component({
    selector: 'app-root',
    template: ``,
    styles: []
})
export class AppComponent {
}

I see a Cannot load module "example.txt" error in WebStorm, and when I run ng build and I get the following error.

ERROR in src/app/app.component.ts(2,17): error TS2307: Cannot find module 'example.txt'

So I Googled how to resolve this issue and I found this answer.

How to import JSON File into a TypeScript file?

I then add a /src/typings.d.ts file with the following contents, and this fixes the error in WebStorm.

declare module "*.txt" {
    const value: string;
    export default value;
}

I run ng build again and the error message changes to say it can't find the module.

Module not found: Error: Can't resolve 'example.txt' in 'C:\work\temp\example\src\app'

After some lengthy Googling, I figure that I need to add a raw-loader to Angular using a custom webpack configuration. Which leads me to this blog post with instructions.

https://codeburst.io/customizing-angular-cli-6-build-an-alternative-to-ng-eject-a48304cd3b21

So I install custom-webpack

npm i -D @angular-builders/custom-webpack

I edit my angular.json so that the build uses extra-webpack.config.js like so.

          "builder": "@angular-builders/custom-webpack:browser",
          "options": {
            "customWebpackConfig": {
              "path": "./extra-webpack.config.js"
            },

I create the extra-webpack.config.js in the same folder as angular.json with the following contents.

module.exports = {
    module: {
        rules: [
            {
                test: /\.txt$/,
                use: 'raw-loader'
            }
        ]
    }
};

I try building again ng build but get the same error.

Module not found: Error: Can't resolve 'example.txt' in 'C:\work\temp\example\src\app'

I have been unable to get past this point, and everything I've Googled so far seems to imply that this is how it's supposed to be done. Module not found error messages are very broad and I can not find anything specific to Angular 7.

like image 433
Reactgular Avatar asked Apr 16 '19 18:04

Reactgular


2 Answers

I figured it out, and the answer was on the raw-loader documentation page. At the bottom it explains that you have to prefix the import path with raw-loader!

https://webpack.js.org/loaders/raw-loader/#examples

import {Component} from '@angular/core';
import str from 'raw-loader!./example.txt';

alert(str);

@Component({
    selector: 'app-root',
    template: ``,
    styles: []
})
export class AppComponent {
}

I found this very difficult to figure out. You have to figure out how to get TypeScript to recognise the modules, then you have to configure Angular to use the loader and then you have to know how to correctly import the file.

None of the Google search results showed everything together as it related to Angular 7. So I found this turns up in search results for other people.

like image 151
Reactgular Avatar answered Sep 18 '22 15:09

Reactgular


Working in Angular 9,10 with Ivy

So I finally got it working, from this comment on an issue, here's the steps I took, if anyone else is looking for help.

  1. yarn add -D @angular-builders/custom-webpack raw-loader

  2. Change angular.json to use @angular-builders/custom-webpack

...
"architect": {
  "build": {
    "builder": "@angular-builders/custom-webpack:browser",
    "options": {
      "customWebpackConfig": {
        "path": "./webpack.partial.js"
      },
  ...
  "serve": {
    "builder": "@angular-builders/custom-webpack:dev-server",
    "options": {
      "browserTarget": "PROJECTNAME:build"
    },
  ...
  1. add file webpack.partial.js next to angular.json
module.exports = {
  module: {
    rules: [
      { test: /\.(txt|md)$/, loader: 'raw-loader' }
    ]
  } 
};
  1. add type declaration in file ./types/textfile.d.ts
declare module '!raw-loader!*' {
  const contents: string;
  export = contents;
}
  1. make sure that your tsconfig file knows about textfile.d.ts
{
  "compilerOptions": {
...
    "typeRoots": ["node_modules/@types", "./types"],
...                                       // ^ this is important
}
  1. import your text files using require syntax
import { Component } from '@angular/core';

const myText = require('!raw-loader!./my-text-file.txt');

@Component({
  template: `<pre>{{myText}}</pre>`,
})
export class ChangeLogComponent {
  myText = myText;
}
  1. Done! The project should serve/build in angular 9,10 now
like image 44
Ben Winding Avatar answered Sep 20 '22 15:09

Ben Winding