如何将Webpack 4配置为不捆绑多个scss入口点

时间:2018-08-04 23:16:12

标签: node.js webpack sass

嗨,我有一个webpack配置,它可以根据一个glob条目和一个主要的打字稿文件来获取多个scss文件。问题是它将scss文件捆绑在一起在一个css文件中,而我希望它们基于输入是独立的。 Webpack肯定会看到来自全局的所有文件。 enter image description here

生成的文件是所有3个文件的捆绑包。 我花了数小时的时间在谷歌上搜索,并尝试配置它,这让我发疯:rage:

我能找到的所有内容都显示了如何在手动指定多个输出的同时配置多个输出。或对于带有不受支持插件的旧版Webpack。

这是我当前的配置:

import * as webpack from "webpack";
import * as path from "path";
import * as glob from "glob";
import * as MiniCssExtractPlugin from "mini-css-extract-plugin";

const config: webpack.Configuration = {
  mode: "development",
  entry: glob.sync(
    "./src/themes/**/scss/*.main.scss",
    "./src/ts/theme-pack.ts"
  ),
  module: {
    rules: [
      {
        test: /\.ts?$/,
        use: "ts-loader",
        exclude: /node_modules/
      },
      {
        test: /\.scss$/,
        use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"]
      }
    ]
  },
  resolve: {
    extensions: [".js", ".css", ".ts", ".scss"]
  },
  output: {
    filename: "bundle.js",
    path: path.resolve(__dirname, "./dist")
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: "[name].css",
      chunkFilename: "[name].css"
    })
  ]

  //   //Dev server
  //   devServer: {
  //     contentBase: __dirname,
  //     compress: true,
  //     port: 8080
  // }
};

export default config;

有人可以帮忙吗?看来应该很简单,但是……

编辑

这就是我要去的地方。唯一的问题是它会生成与css同名的js文件。而且我找不到将CSS放入./dist/css并将js放入./dist/js

的方法
import * as webpack from "webpack";
import * as path from "path";
import * as glob from "glob";
import * as MiniCssExtractPlugin from "mini-css-extract-plugin";


let entries = {
  "theme-pack": "./src/ts/theme-pack.ts"
};

function getEntries() {
  const files = glob.sync("./src/themes/**/scss/*.main.scss");
  files.forEach(file => {
    entries[path.basename(file)] = file;
  });
  return entries;
}

function perName() {
  // this function will create Objects that can splitChunks
  // testing each file in its own location
  return glob
    .sync("./src/themes/**/scss/*.main.scss")
    .reduce((obj, filename) => {
      const niceName = path.basename(filename);
      obj[niceName] = {
        test: new RegExp(filename),
        name: niceName,
        chunks: "all",
        enforce: true
      };
      return obj;
    }, {});
}

const config: webpack.Configuration = {
  mode: "development",
  entry: getEntries(),
  output: {
    path: path.resolve(__dirname, "./dist"),
    filename: "[name].js"
  },
  module: {
    rules: [
      {
        test: /\.ts?$/,
        use: "ts-loader",
        exclude: /node_modules/
      },
      {
        test: /\.scss$/,
        use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"]
      }
    ]
  },
  resolve: {
    extensions: [".js", ".css", ".ts", ".scss"]
  },

  plugins: [
    new MiniCssExtractPlugin({
      filename: "[name].css",
    })
  ],
  optimization: {
    splitChunks: {
      cacheGroups: perName()
    }
  }

  //   //Dev server
  //   devServer: {
  //     contentBase: __dirname,
  //     compress: true,
  //     port: 8080
  // }
};

export default config;

1 个答案:

答案 0 :(得分:1)

如我所见,这里有2个选项可以实现这一目标。

1)使用splitChunks

optimization: {
  splitChunks: {
    cacheGroups: {
      adminLteStyles: {
        name: 'admin-lte',
        test: /admin-lte\.main\.scss$/,
        chunks: 'all',
        enforce: true
      },
      coreUiStyles: {
        name: 'coreui',
        test: /coreui\.main\.scss$/,
        chunks: 'all',
        enforce: true
      },

      // ... more

    }
  }
},

但是正如您所看到的,这需要为您拥有的每个css文件编写一个regex块...当然,您可以创建一个负责该功能的函数...

function perTheme() {
  // this function will create Objects that can splitChunks
  // testing if the file is located under a specific theme directory
  return glob.sync("./src/themes/*/")
    .reduce((obj, theme) => {
      const niceName = path.basename(theme)
      obj[niceName] = {
        test: new RegExp(theme + "(.*).main.scss"),
        name: niceName,
        chunks: 'all',
        enforce: true
      }
      return obj;
    }, {})
}

function perName() {
  // this function will create Objects that can splitChunks
  // testing each file in its own location
  return glob.sync("./src/themes/*/scss/*.main.scss")
    .reduce((obj, filename) => {
      const niceName = path.basename(filename)
      obj[niceName] = {
        test: new RegExp(filename),
        name: niceName,
        chunks: 'all',
        enforce: true
      }
      return obj;
    }, {})
}

// in your webpack config ...


optimization: {
    splitChunks: {
      cacheGroups: perTheme()
      // this will create one css file per theme
      // admin-lte theme etc..
    }
}

// OR

optimization: {
    splitChunks: {
      cacheGroups: perName()
      // this will create one css file per scss you have
    }
}

我知道这可能很难配置,但是请记住,使用此方法拆分块非常强大。您可以通过多种方法拆分文件。如果您觉得太多,请检查第二个选项!

2)使用提取加载程序

module: {
  rules: [{
    test: /\.scss$/,
    use: [{
        loader: 'file-loader',
        options: {
          name: "[name]-dist.[ext]",
        },
      },
      'extract-loader',
      "css-loader",
      "sass-loader"
    ]
  }]
}

因此,除了使用MiniCssExtractPlugin之外,您还可以简单地使用上述配置。这样,每个scss文件将转换为css,将解析每个导入,然后使用extract-loader,您将获得字符串格式的原始css。之后,file-loader将输出带有原始css的文件。因此,最终将每个scss文件转换为每个css相等。但是,您可以看到,这种简单的方法为您提供了比第一种方法更少的分割块的方法!