JHipster - 如何直接使用 Angular 7 编译 SCSS 文件

标签 jhipster angular7

通常,将 SCSS 样式添加到具有角度组件的组件非常容易(只需创建 scss 文件并将其导入到 component.ts 中),但是此样式不会渲染到普通的 css 文件中,样式是嵌入的(来自据我所知,我对角度很陌生)。

这会产生一个问题,我正在尝试使用 theme with some dinamic skins带有“自定义面板”,但该组件需要独立地指向我编译的CSS的路径。

为了实现这一点,在供应商基本应用程序中,我可以看到他们将其添加到 angular.js 中:

{
  ...
  "projects": {
    "angular-starter": {
      ...,
      "architect": {
        "build": {
          "builder": "@angular-devkit/build-angular:browser",
          "options": {
            "outputPath": "dist/angular-starter",
            "index": "src/index.html",
            "main": "src/main.ts",
            "polyfills": "src/polyfills.ts",
            "tsConfig": "src/tsconfig.app.json",
            "assets": [
              "src/favicon.ico",
              "src/assets"
            ],
            "styles": [
              "src/styles.scss",

              { "input": "src/vendor/styles/appwork.scss", "bundleName": "vendor/styles/appwork", "lazy": true },
              { "input": "src/vendor/styles/appwork-material.scss", "bundleName": "vendor/styles/appwork-material", "lazy": true },
              { "input": "src/vendor/styles/bootstrap.scss", "bundleName": "vendor/styles/bootstrap", "lazy": true },
              { "input": "src/vendor/styles/bootstrap-material.scss", "bundleName": "vendor/styles/bootstrap-material", "lazy": true },
              // More styles like this
            ],
            ...

然后可以直接作为css文件引用,如索引所示:

<html lang="en" class="default-style">
  <head>
    ...
    <!-- Here it references the compiled scss as css directly -->
    <link rel="stylesheet" href="vendor/styles/bootstrap.css" class="theme-settings-bootstrap-css">
    <link rel="stylesheet" href="vendor/styles/appwork.css" class="theme-settings-appwork-css">
    <link rel="stylesheet" href="vendor/styles/theme-corporate.css" class="theme-settings-theme-css">
    <link rel="stylesheet" href="vendor/styles/colors.css" class="theme-settings-colors-css">
    <link rel="stylesheet" href="vendor/styles/uikit.css">

    ...
    <script>
      // Here uses the path of the compiled css as parameter,
      // this way the skin selector changes the css used in the page
      window.themeSettings = new ThemeSettings({
        cssPath: 'vendor/styles/',
        themesPath: 'vendor/styles/'
      });
    </script>

  </head>
  ...
</html>

但是

检查从 jhipster 生成的 angular.js,我可以看到架构师部分是空的:

{
    "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
    "version": 1,
    "newProjectRoot": "projects",
    "projects": {
        "consuldent": {
            "root": "",
            "sourceRoot": "src/main/webapp",
            "projectType": "application",
            "architect": {}
        }
    },

我不知道这是否是因为在示例代码中它使用 ngserve 来运行演示页面,使用node.js服务器,其中jhipster直接使用spring,我尝试添加样式jhipster 的 angular.js 文件的一部分,但我找不到任何可以加载 css 的路径,所以我猜测它只是忽略了我添加的代码

最佳答案

在 Angular 中, View 封装有每个唯一的属性。

在主组件中添加encapsulation: ViewEncapsulation.None,这样CSS将被所有组件共享

import { Component, ViewEncapsulation } from '@angular/core';
@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss'],
  encapsulation: ViewEncapsulation.None
})
export class AppComponent {
  name = 'Angular app';
}

Jhipster 使用 webpack 来打包 Angular 模块。您想捆绑 css 因此 将您的 css 复制到 /src/main/webapp/vendor/styles/appwork.css' 在 webpack.common.js 中添加一个条目

new CopyWebpackPlugin([
    { from: './node_modules/swagger-ui/dist/css', to: 'swagger-ui/dist/css' },
    { from: './node_modules/swagger-ui/dist/lib', to: 'swagger-ui/dist/lib' },
    { from: './node_modules/swagger-ui/dist/swagger-ui.min.js', to: 'swagger-ui/dist/swagger-ui.min.js' },
    { from: './src/main/webapp/swagger-ui/', to: 'swagger-ui' },
    { from: './src/main/webapp/content/', to: 'content' },        
    { from: './src/main/webapp/vendor/styles/appwork.css', to: 'content/vendor/styles/appwork.css' },    
    { from: './src/main/webapp/favicon.ico', to: 'favicon.ico' },
    { from: './src/main/webapp/manifest.webapp', to: 'manifest.webapp' },
    // jhipster-needle-add-assets-to-webpack - JHipster will add/remove third-party resources in this array
    { from: './src/main/webapp/robots.txt', to: 'robots.txt' }
]),

编译自定义 sass

webpack.prod.js 中添加条目,例如 myfilemyfile2。然后更改sass编译器以包含我们的myfile.scss、myfile2.scss,最后注释掉MiniCssExtractPlugin

    entry: {
    polyfills: './src/main/webapp/app/polyfills',
    global: './src/main/webapp/content/scss/global.scss',
    myfile: './src/main/webapp/content/scss/myfile.scss',
    myfile2: './src/main/webapp/content/scss/myfile2.scss',
    main: './src/main/webapp/app/app.main'
  },
 .
 .
 .
 .
  exclude: /(vendor\.scss|global\.scss|myfile\.scss|myfile2\.scss)/
 .
 .
 .
 .
 test: /(vendor\.scss|global\.scss|myfile\.scss|myfile2\.scss)/ 
 .
 .
 .
 .
 exclude: /(vendor\.css|global\.css|myfile\.css|myfile2\.css)/
 .
 .
 .
 .
 test: /(vendor\.css|global\.css|myfile\.css|myfile2\.css)/,
 .
 .
 .
 .
     new MiniCssExtractPlugin({
        // Options similar to the same options in webpackOptions.output
        // both options are optional
       // filename: '[name].[contenthash].css',
        // chunkFilename: '[id].css'
    }),

您的 webpack.prod.js 文件如下所示

    const webpack = require('webpack');
    const webpackMerge = require('webpack-merge');
    const MiniCssExtractPlugin = require('mini-css-extract-plugin');
    const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
    const Visualizer = require('webpack-visualizer-plugin');
    const MomentLocalesPlugin = require('moment-locales-webpack-plugin');
    const TerserPlugin = require('terser-webpack-plugin');
    const WorkboxPlugin = require('workbox-webpack-plugin');
    const AngularCompilerPlugin = require('@ngtools/webpack').AngularCompilerPlugin;
    const path = require('path');

    const utils = require('./utils.js');
    const commonConfig = require('./webpack.common.js');

    const ENV = 'production';
    const sass = require('sass');

    module.exports = webpackMerge(commonConfig({ env: ENV }), {
        // Enable source maps. Please note that this will slow down the build.
        // You have to enable it in UglifyJSPlugin config below and in tsconfig-aot.json as well
        // devtool: 'source-map',
        entry: {
            polyfills: './src/main/webapp/app/polyfills',
            global: './src/main/webapp/content/scss/global.scss',
            myfile: './src/main/webapp/content/scss/myfile.scss',
            myfile2: './src/main/webapp/content/scss/myfile2.scss',
            main: './src/main/webapp/app/app.main'
        },
        output: {
            path: utils.root('build/www'),
            filename: 'app/[name].[hash].bundle.js',
            chunkFilename: 'app/[id].[hash].chunk.js'
        },
        module: {
            rules: [{
                test: /(?:\.ngfactory\.js|\.ngstyle\.js|\.ts)$/,
                loader: '@ngtools/webpack'
            },
            {
                test: /\.scss$/,
                use: ['to-string-loader', 'css-loader', {
                    loader: 'sass-loader',
                    options: { implementation: sass }
                }],
                exclude: /(vendor\.scss|global\.scss|myfile\.scss|myfile2\.scss)/
            },
            {
                test: /(vendor\.scss|global\.scss|myfile\.scss|myfile2\.scss)/,
                use: [
                    MiniCssExtractPlugin.loader,
                    'css-loader',
                    'postcss-loader',
                    {
                        loader: 'sass-loader',
                        options: { implementation: sass }
                    }
                ]
            },
            {
                test: /\.css$/,
                use: ['to-string-loader', 'css-loader'],
                exclude: /(vendor\.css|global\.css|myfile\.css|myfile2\.css)/
            },
            {
                test: /(vendor\.css|global\.css|myfile\.css|myfile2\.css)/,
                use: [
                    MiniCssExtractPlugin.loader,
                    'css-loader',
                    'postcss-loader'
                ]
            }]
        },
        optimization: {
            runtimeChunk: false,
            splitChunks: {
                cacheGroups: {
                    commons: {
                        test: /[\\/]node_modules[\\/]/,
                        name: 'vendors',
                        chunks: 'all'
                    }
                }
            },
            minimizer: [
                new TerserPlugin({
                    parallel: true,
                    cache: true,
                    terserOptions: {
                        ie8: false,
                        // sourceMap: true, // Enable source maps. Please note that this will slow down the build
                        compress: {
                            dead_code: true,
                            warnings: false,
                            properties: true,
                            drop_debugger: true,
                            conditionals: true,
                            booleans: true,
                            loops: true,
                            unused: true,
                            toplevel: true,
                            if_return: true,
                            inline: true,
                            join_vars: true
                        },
                        output: {
                            comments: false,
                            beautify: false,
                            indent_level: 2
                        }
                    }
                }),
                new OptimizeCSSAssetsPlugin({})
            ]
        },
        plugins: [
             new MiniCssExtractPlugin({
                 // Options similar to the same options in webpackOptions.output
                 // both options are optional
                // filename: '[name].[contenthash].css',
                 // chunkFilename: '[id].css'
             }),
            new MomentLocalesPlugin({
                localesToKeep: [
                        'en',
                        'es'
                        // jhipster-needle-i18n-language-moment-webpack - JHipster will add/remove languages in this array
                    ]
            }),
            new Visualizer({
                // Webpack statistics in target folder
                filename: '../stats.html'
            }),
            new AngularCompilerPlugin({
                mainPath: utils.root('src/main/webapp/app/app.main.ts'),
                tsConfigPath: utils.root('tsconfig-aot.json'),
                sourceMap: true
            }),
            new webpack.LoaderOptionsPlugin({
                minimize: true,
                debug: false
            }),
            new WorkboxPlugin.GenerateSW({
              clientsClaim: true,
              skipWaiting: true,
            })
        ],
        mode: 'production'
    });

webpack.dev.js执行相同的步骤

const webpack = require('webpack');
const writeFilePlugin = require('write-file-webpack-plugin');
const webpackMerge = require('webpack-merge');
const BrowserSyncPlugin = require('browser-sync-webpack-plugin');
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
const FriendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin');
const SimpleProgressWebpackPlugin = require('simple-progress-webpack-plugin');
const WebpackNotifierPlugin = require('webpack-notifier');
const path = require('path');
const sass = require('sass');

const utils = require('./utils.js');
const commonConfig = require('./webpack.common.js');

const ENV = 'development';

module.exports = (options) => webpackMerge(commonConfig({ env: ENV }), {
    devtool: 'eval-source-map',
    devServer: {
        contentBase: './build/www',
        proxy: [{
            context: [
                /* jhipster-needle-add-entity-to-webpack - JHipster will add entity api paths here */
                '/api',
                '/management',
                '/swagger-resources',
                '/v2/api-docs',
                '/h2-console',
                '/auth'
            ],
            target: `http${options.tls ? 's' : ''}://127.0.0.1:8080`,
            secure: false,
            changeOrigin: options.tls,
            headers: { host: 'localhost:9000' }
        }],
        stats: options.stats,
        watchOptions: {
            ignored: /node_modules/
        }
    },
    entry: {
        polyfills: './src/main/webapp/app/polyfills',
        global: './src/main/webapp/content/scss/global.scss',
        myfile: './src/main/webapp/content/scss/myfile.scss',
        myfile2: './src/main/webapp/content/scss/myfile2.scss',
        main: './src/main/webapp/app/app.main'
    },
    output: {
        path: utils.root('build/www'),
        filename: 'app/[name].bundle.js',
        chunkFilename: 'app/[id].chunk.js'
    },
    module: {
        rules: [{
            test: /\.ts$/,
            enforce: 'pre',
            loader: 'tslint-loader',
            exclude: [/(node_modules)/, new RegExp('reflect-metadata\\' + path.sep + 'Reflect\\.ts')]
        },
        {
            test: /\.ts$/,
            use: [
                'angular2-template-loader',
                {
                    loader: 'cache-loader',
                    options: {
                      cacheDirectory: path.resolve('build/cache-loader')
                    }
                },
                {
                    loader: 'thread-loader',
                    options: {
                        // there should be 1 cpu for the fork-ts-checker-webpack-plugin
                        workers: require('os').cpus().length - 1
                    }
                },
                {
                    loader: 'ts-loader',
                    options: {
                        transpileOnly: true,
                        happyPackMode: true
                    }
                },
                'angular-router-loader'
            ],
            exclude: /(node_modules)/
        },
        {
            test: /\.scss$/,
            use: ['to-string-loader', 'css-loader', {
                loader: 'sass-loader',
                options: { implementation: sass }
            }],
            exclude: /(vendor\.scss|global\.scss|myfile\.scss|myfile2\.scss)/
        },
        {
            test: /(vendor\.scss|global\.scss|myfile\.scss|myfile2\.scss)/,
            use: ['style-loader', 'css-loader', 'postcss-loader', {
                loader: 'sass-loader',
                options: { implementation: sass }
            }]
        },
        {
            test: /\.css$/,
            use: ['to-string-loader', 'css-loader'],
            exclude: /(vendor\.css|global\.css|myfile\.css|myfile2\.css)/
        },
        {
            test: /(vendor\.css|global\.css|myfile\.css|myfile2\.css)/,
            use: ['style-loader', 'css-loader']
        }]
    },
    stats: process.env.JHI_DISABLE_WEBPACK_LOGS ? 'none' : options.stats,
    plugins: [
        process.env.JHI_DISABLE_WEBPACK_LOGS
            ? null
            : new SimpleProgressWebpackPlugin({
                format: options.stats === 'minimal' ? 'compact' : 'expanded'
              }),
        new FriendlyErrorsWebpackPlugin(),
        new ForkTsCheckerWebpackPlugin(),
        new BrowserSyncPlugin({
            host: 'localhost',
            port: 9000,
            proxy: {
                target: 'http://localhost:9060'
            },
            socket: {
                clients: {
                    heartbeatTimeout: 60000
                }
            }
        }, {
            reload: false
        }),
        new webpack.ContextReplacementPlugin(
            /angular(\\|\/)core(\\|\/)/,
            path.resolve(__dirname, './src/main/webapp')
        ),
        new writeFilePlugin(),
        new webpack.WatchIgnorePlugin([
            utils.root('src/test'),
        ]),
        new WebpackNotifierPlugin({
            title: 'JHipster',
            contentImage: path.join(__dirname, 'logo-jhipster.png')
        })
    ].filter(Boolean),
    mode: 'development'
});

然后,如果您希望 css 包含在您的 index.html 中,请更改 webpack.common.js

new HtmlWebpackPlugin({
    template: './src/main/webapp/index.html',
    chunks: ['vendors', 'polyfills', 'main', 'global','myfile','myfile2'],
    chunksSortMode: 'manual',
    inject: 'body'
})

关于JHipster - 如何直接使用 Angular 7 编译 SCSS 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54684252/

相关文章:

logging - slf4j.Logger未导入到jHipster项目

Angular7 Reactive Forms 输入属性值不会在 Controller /组件中更改,仅在 HTML 标记上更改

jquery - Angular CLI 7.1.4 中未加载外部 JS 文件

node.js - jhipster/spring boot - 尝试代理请求时发生错误

rest - Jhipster + REST 客户端 + 身份验证

java - 架构 微服务 Jhipster

angular7 - Angular 7 向服务器发送多个文件

hook - Ionic 4/Angular 7 生命周期钩子(Hook)每页只调用一次

angular - 在 <agm-direction> 中拖动原点时方向发生变化时获取坐标

javascript - Angular 4 : rendering different with input type color in a form or not