webpack hot module replacement:css without refresh

时间:2015-06-14 18:38:59

标签: webpack webpack-dev-server

到目前为止,我一直在使用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'
            }
        ]
    }
};

5 个答案:

答案 0 :(得分:17)

这是使用the project README中所述的ExtractTextPlugin的缺点之一。您可以通过拆分配置来解决此问题。 IE浏览器。有没有它的开发单独配置和一个用于生产的配置。

答案 1 :(得分:4)

现在可以使用angular2,webpack和热模块替换,sass源图以及外部加载的css。我花了好几天的时间玩它,但我让它运转了!

依赖项是style-loadercss-loadersass-loader(如果使用sass,如果没有,则可以删除sass加载程序)

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

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

此配置允许使用webpack dev服务器替换使用SCSS文件的热模块,并使用extracttextplugin替换生产模式以发出实际的.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,您需要app.style.scss文件 @Component装饰器的外部

这就是诀窍。如果使用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编译。

答案 2 :(得分:3)

实际上有一种简单的方法可以做到这一点。我正在使用sass-loader和extract-text-plugin生成css文件。

您需要做的是为您的css添加ID

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

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

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以重新加载它。

答案 3 :(得分:0)

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

答案 4 :(得分:0)

在使用preactprefresh的webpack 5中,我将hot: true更改为hotOnly: true,样式发生了更改,而无需重新加载。