使用webpack生成静态CSS文件

7
我目前正在开发一个应用程序,该应用程序使用不同的前端主题。这些主题只是 CSS 文件,用户可以选择它们。
从技术上讲,这些主题是 .scss 文件,通过 webpack 编译并通过标准链接标签在 angular 中加载: <link rel="stylesheet", ng-href="themes/{{theme}}.css"> 我的简化的 webpack 配置如下:
theme1CssExtractor = new ExtractTextPlugin('themes/theme-1.css'),     
theme2CssExtractor = new ExtractTextPlugin('themes/theme-2.css'),     

module.exports = new WebpackConfig().merge({

entry: {
    app: [
        './app/main.ts',
        './assets/sass/themes/theme-1.scss',
        './assets/sass/themes/theme-2.scss'
    ],
},

output: {
    path: "build/",
    filename: "[name].bundle.js",
    publicPath: "/build/"
},

plugins: [
    theme1CssExtractor,
    theme2CssExtractor,
],

module: {
    loaders: [
        {
            test: /\.ts$/,
            loaders: ['awesome-typescript-loader']
        },
        [
            {
                test: /theme-1\.scss$/,
                include: path.resolve(__dirname, "assets/sass/themes"),
                loader: theme1CssExtractor.extract(
                    "style",
                    "css!sass?includePaths[]=" + path.resolve(__dirname, './node_modules/compass-mixins/lib')
                )
            },
            {
                test: /theme-2\.scss$/,
                include: path.resolve(__dirname, "assets/sass/themes"),
                loader: theme2CssExtractor.extract(
                    "style",
                    "css!sass?includePaths[]=" + path.resolve(__dirname, './node_modules/compass-mixins/lib')
                )
            }
        ]
    ]
}

在启用热模块替换(HMR)功能的webpack-dev-server中,extractTextPlugin不支持HMR,因此这种方法无法正常工作。如果简单禁用extractTextPlugin(options.disable)或将其删除,则所有主题都会编译到主模块中,这当然会破坏主题,因为所有主题都被一起应用。

如何直接使用webpack生成这些CSS文件而不使用extractTextPlugin?我尝试了各种尝试,包括不同的entries/chunks、file-loader等,但仍然没有真正解决问题。

应该很简单:从SCSS-Files生成静态CSS-Files,而不将它们转换为JS-Files,也不使用ExtractTextPlugin。

如果有人能指点我正确的方向,那将非常棒。

1个回答

2
一种方法是按照不同的模式组织Webpack配置:
  • 开发模式:不使用ExtractTextPlugin(稍后会讨论包含所有内容的一个文件的问题)
  • 生产模式:像现在一样使用ExtractTextPlugin

你可以看一下este中是如何实现的。

关于没有ExtractTextPlugin时出现的问题(一个包含所有主题的文件):这是因为你的配置在'app'块中同时包含了'theme-1.scss'和'theme-2.scss',所以Webpack将它们放在一起(一个块)。你可以尝试另一种方法:将它们从入口点列表中排除,并在源代码中添加类似以下内容:

require('../assets/sass/themes/' + theme + '.scss');

在开发模式下,根据变量“theme”的值,只会加载一个模块(主题)。而在生产模式下,Webpack将遍历“assets/sass/themes/”中的所有文件(当'require'包含表达式时是特定的Webpack行为),将它们作为模块包含进来,然后ExtractTextPlugin将处理它们的提取(因此您不必在这里做任何事情)。
关于如何在生产环境下加载特定主题有一些棘手的部分(因为您代码中的“require”将无效,ExtractTextPlugin将使相应的模块为空),因此您需要添加一些代码将< link >添加到HTML的< head >中。同时,这段代码在开发模式下不应该被调用。一个肮脏的技巧可以帮助实现这一点:
if (!__DEV__) {
  // do adding <link> to the <head>
}

(参见此示例中 DefinePlugin 如何用于定义 __DEV__ 变量)。
我真的很想知道有没有更好的解决方法...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接