21

到目前为止,我一直在使用 livereload,这样每当我更改 JS 或模板时,页面都会刷新,当我更改 CSS 时,它会在不刷新的情况下热交换新的 CSS。

我现在正在尝试 webpack,几乎得到了相同的行为,除了一个例外:当 CSS 更改时,它会刷新整个窗口。是否可以在不刷新的情况下使其热交换 CSS?

到目前为止的配置:

var webpackConfig = {
    entry: ["webpack/hot/dev-server", __dirname + '/app/scripts/app.js'],
    debug: true,
    output: {
        path: __dirname + '/app',
        filename: 'scripts/build.js'
    },
    devtool: 'source-map',
    plugins: [
        new webpack.HotModuleReplacementPlugin(),
        new htmlWebpackPlugin({
            template: __dirname + '/app/index.html',
            inject: 'body',
            hash: true,
            config: config
        }),
        new webpack.ProvidePlugin({
            'angular': 'angular'
        }),
        new ExtractTextPlugin("styles.css")
    ],
    module: {
        loaders: [
            {
                test: /\.scss$/,
                loader: "style!css!sass?includePaths[]=" + __dirname + "/app/bower_components/compass-mixins/lib&includePaths[]=" + __dirname + '/instance/sth/styles&includePaths[]=' + __dirname + '/app/scripts'
            }
        ]
    }
};
4

6 回答 6

17

这是项目 READMEExtractTextPlugin中所述使用的缺点之一。您可以通过拆分配置来解决问题。IE。在没有它的情况下有单独的开发配置和一个用于生产的配置。

于 2015-06-16T07:06:56.193 回答
4

现在可以使用 angular2、带有热模块替换的 webpack、sass 源映射和外部加载的 css。我花了几天的时间玩它,但我让它工作了!

依赖项是style-loader, css-loader, 和sass-loader(如果使用 sass,如果没有,可以删除 sass 加载器)

我将 ExtractTextPlugin 用于生产模式以发出实际的 .css 文件。

注意:为了让它工作,我不使用 stylesUrl 属性,而是在 @Component 装饰器之外导入 .scss 文件,以便样式在全局上下文中加载,而不是由组件限定。

此配置允许使用 webpack 开发服务器用 SCSS 文件替换热模块,并为生产模式提取文本插件以发出实际的 .css 文件。

这是我的工作配置

{
        test: /\.(scss)$/,
        use:
          isDevServer ? [
              {
                loader: 'style-loader',
              },             
              {
                loader: 'css-loader',
                options: { sourceMap: true }
              },
              {
                loader: 'postcss-loader',
                options: { postcss: [AutoPrefixer(autoPrefixerOptions)], sourceMap: true }
              },
              {
                loader: 'sass-loader',
                options: { sourceMap: true }
              },
              {
                loader: 'sass-resources-loader',
                options: {
                  resources: [
                    './src/assets/styles/variables.scss',
                    './src/assets/styles/mixins.scss']
                }
              }, 
              /**
               * The sass-vars-loader will convert the 'vars' property or any module.exports of 
               * a .JS or .JSON file into valid SASS and append to the beginning of each 
               * .scss file loaded.
               *
               * See: https://github.com/epegzz/sass-vars-loader
               */
              {
                loader: '@epegzz/sass-vars-loader?',
                options: querystring.stringify({
                  vars: JSON.stringify({
                    susyIsDevServer: susyIsDevServer
                  })
                })
              }] : // dev mode
          ExtractTextPlugin.extract({
            fallback: "css-loader",
            use: [
              {
                loader: 'css-loader',
                options: { sourceMap: true }
              },
              {
                loader: 'postcss-loader',
                options: { postcss: [AutoPrefixer(autoPrefixerOptions)], sourceMap: true }
              },
              {
                loader: 'sass-loader',
                options: { sourceMap: true }
              },
              {
                loader: 'sass-resources-loader',
                options: {
                  resources: [
                    './src/assets/styles/variables.scss',
                    './src/assets/styles/mixins.scss']
                }
              }, {
                loader: '@epegzz/sass-vars-loader?',
                options: querystring.stringify({
                  vars: JSON.stringify({
                    susyIsDevServer: susyIsDevServer
                  })
                  // // Or use 'files" object to specify vars in an external .js or .json file
                  // files: [
                  //    path.resolve(helpers.paths.appRoot + '/assets/styles/sass-js-variables.js')
                  // ],
                })
              }],
            publicPath: '/' // 'string' override the publicPath setting for this loader
          })
      },

然后,在您的组件中,例如,app.component.ts您需要在 @Component 装饰器之外app.style.scss的文件。

这就是诀窍。如果您使用“角度方式”加载样式,这将不起作用stylesUrl。这样做可以让您为延迟加载.css的组件延迟加载样式表,从而使初始加载时间更快。

app.component.css

/*
 * THIS IS WHERE WE REQUIRE CSS/SCSS FILES THAT THIS COMPONENT NEEDS
 *
 * Function: To enable so-called "Lazy Loading" CSS/SCSS files "on demand" as the app views need them.
 * Do NOT add styles the "Angular2 Way" in the @Component decorator ("styles" and "styleUrls" properties)
 */
    import './app.style.scss'

/**
 * AppComponent Component
 * Top Level Component
 */
@Component({
   selector: 'body',
   encapsulation: ViewEncapsulation.None,
   host: { '[class.authenticated]': 'appState.state.isAuthenticated' },
   templateUrl: './app.template.html'
})

我运行这个设置没有问题。干得好!

sass_sourcemaps _hmr _wds

更新于 08/2017:改进了 webpack 3+ 架构要求的配置,并与 Angular 4 AOT 编译一起使用。

于 2016-05-20T21:38:59.757 回答
4

实际上有一个简单的方法可以做到这一点。我正在使用带有提取文本插件的 sass-loader 来生成 css 文件。

您需要做的是将 id 添加到您的 css 包括

  <link id="js-style" type="text/css" rel="stylesheet" href="/static/main.css">

现在,您需要确保在发生 HMR 时使用当前版本/时间戳更新 url。你可以这样做:

import '../style/main.scss'
if (module.hot) {
  module.hot.accept('../style/main.scss', () => {
    const baseStyle = window.document.getElementById('js-style')
    baseStyle.setAttribute('href', '/static/main.css?v=' + new Date().valueOf)
  })
}

因此,每当 css 发生变化时,我们都会修复 css include 的 url 以重新加载它。

于 2017-02-09T08:12:55.203 回答
1

尽管 ExtractTextPlugin 在其README 部分中声明“无热模块替换” ,但我通过 BrowserSync API 手动更新 CSS 文件来解决此问题

我使用凝视来监听我的 CSS 文件中的任何更改,然后使用 BrowserSync 来更新它们。

    npm install gaze

您也可以通过使用以下内容编辑构建脚本来轻松完成此操作:

  const { Gaze } = require('gaze');

  // Your own BrowserSync init
  browserSync.init({
    ...
  }, resolve);

  // Create a watcher:
  // You can watch/reload specific files according to your build/project structure
  const gaze = new Gaze('**/*.css');
  gaze.on('all', () => bs.reload('*.css'));

希望有帮助。

于 2016-12-04T00:29:32.970 回答
0

您可以使用“css-hot-loader”为提取的 css 启用 HMR。它非常适合我。

于 2018-03-21T11:25:58.573 回答
0

在使用 preact 和 prefresh 的 webpack 5 中tohot: truehotOnly: true样式更改为没有重新加载。

于 2020-11-26T20:17:44.233 回答