有没有办法让Webpack将编译好的SCSS→CSS文件添加到我的角项目的index.html head中作为内联样式标记?
目的是为“装载.”设计风格。页面显示时角是繁忙的引导。为了避免FOUC,需要在index.html的头上插入CSS文件,作为样式标记。这样,一旦加载了index.html,我们就不需要等待另一个网络资源的加载才能看到我们的预引导样式。
这也可能是将index.html页面内的小徽标内联为base64数据URI的一种有价值的方法。
该项目是用角CLI创建的,Webpack 2使用了角4。我用ng eject弹出Webpack的配置,并对webpack.config.js做了一些小的修改。我只从配置中删除了更少的支持和Stylus支持。
这里是我的webpack.config.js供参考:
const path = require('path');
const ProgressPlugin = require('webpack/lib/ProgressPlugin');
const ProvidePlugin = require('webpack/lib/ProvidePlugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const autoprefixer = require('autoprefixer');
const postcssUrl = require('postcss-url');
const {NoEmitOnErrorsPlugin, LoaderOptionsPlugin} = require('webpack');
const {GlobCopyWebpackPlugin, BaseHrefWebpackPlugin} = require('@angular/cli/plugins/webpack');
const {CommonsChunkPlugin} = require('webpack').optimize;
const {AotPlugin} = require('@ngtools/webpack');
const nodeModules = path.join(process.cwd(), 'node_modules');
const entryPoints = ["inline", "polyfills", "sw-register", "styles", "twbs", "vendor", "main"];
const baseHref = "";
const deployUrl = "";
module.exports = {
devtool: "source-map",
devServer: {
port: 4200,
host: "0.0.0.0",
historyApiFallback: true
},
resolve: {
extensions: [
".ts",
".js"
],
modules: [
"./node_modules"
]
},
resolveLoader: {
modules: [
"./node_modules"
]
},
entry: {
main: [
"./src/main.ts"
],
polyfills: [
"./src/polyfills.ts"
],
styles: [
"./src/styles/styles.scss",
"./src/styles/vendor.scss"
],
twbs: 'bootstrap-loader'
},
output: {
path: path.join(process.cwd(), "dist"),
filename: "[name].bundle.js",
chunkFilename: "[id].chunk.js"
},
module: {
rules: [
{
enforce: "pre",
test: /\.js$/,
loader: "source-map-loader",
exclude: [
/node_modules/
]
},
{
test: /\.json$/,
loader: "json-loader"
},
{
test: /\.html$/,
loader: "raw-loader"
},
{
test: /\.(eot|svg)$/,
loader: "file-loader?name=[name].[hash:20].[ext]"
},
{
test: /\.(jpg|png|gif|otf|ttf|woff|woff2|cur|ani)$/,
loader: "url-loader?name=[name].[hash:20].[ext]&limit=10000"
},
{
exclude: [
path.join(process.cwd(), "src/styles/styles.scss"),
path.join(process.cwd(), "src/styles/vendor.scss")
],
test: /\.css$/,
loaders: [
"exports-loader?module.exports.toString()",
"css-loader?{\"sourceMap\":false,\"importLoaders\":1}",
"postcss-loader"
]
},
{
exclude: [
path.join(process.cwd(), "src/styles/styles.scss"),
path.join(process.cwd(), "src/styles/vendor.scss")
],
test: /\.scss$/,
loaders: [
"exports-loader?module.exports.toString()",
"css-loader?{\"sourceMap\":false,\"importLoaders\":1}",
"postcss-loader",
"sass-loader"
]
},
{
include: [
path.join(process.cwd(), "src/styles/styles.scss"),
path.join(process.cwd(), "src/styles/vendor.scss")
],
test: /\.css$/,
loaders: ExtractTextPlugin.extract({
use: [
"css-loader?{\"sourceMap\":false,\"importLoaders\":1}",
"postcss-loader"
],
fallback: "style-loader",
publicPath: ""
})
},
{
include: [
path.join(process.cwd(), "src/styles/styles.scss"),
path.join(process.cwd(), "src/styles/vendor.scss")
],
test: /\.scss$/,
loaders: ExtractTextPlugin.extract({
use: [
"css-loader?{\"sourceMap\":false,\"importLoaders\":1}",
"postcss-loader",
"sass-loader"
],
fallback: "style-loader",
publicPath: ""
})
},
{
test: /\.ts$/,
loader: "@ngtools/webpack"
}
]
},
plugins: [
new ProvidePlugin({
$: "jquery",
jQuery: "jquery",
"window.jQuery": "jquery",
Tether: "tether",
"window.Tether": "tether",
Tooltip: "exports-loader?Tooltip!bootstrap/js/dist/tooltip",
Alert: "exports-loader?Alert!bootstrap/js/dist/alert",
Button: "exports-loader?Button!bootstrap/js/dist/button",
Carousel: "exports-loader?Carousel!bootstrap/js/dist/carousel",
Collapse: "exports-loader?Collapse!bootstrap/js/dist/collapse",
Dropdown: "exports-loader?Dropdown!bootstrap/js/dist/dropdown",
Modal: "exports-loader?Modal!bootstrap/js/dist/modal",
Popover: "exports-loader?Popover!bootstrap/js/dist/popover",
Scrollspy: "exports-loader?Scrollspy!bootstrap/js/dist/scrollspy",
Tab: "exports-loader?Tab!bootstrap/js/dist/tab",
Util: "exports-loader?Util!bootstrap/js/dist/util"
}),
new NoEmitOnErrorsPlugin(),
new GlobCopyWebpackPlugin({
patterns: [
"assets",
"favicon.ico"
],
globOptions: {
"cwd": "./src",
"dot": true,
"ignore": "**/.gitkeep"
}
}),
new ProgressPlugin(),
new HtmlWebpackPlugin({
template: "./src/index.html",
filename: "./index.html",
hash: false,
inject: true,
compile: true,
favicon: false,
minify: false,
cache: true,
showErrors: true,
chunks: "all",
excludeChunks: [],
title: "Webpack App",
xhtml: true,
chunksSortMode: function sort(left, right) {
let leftIndex = entryPoints.indexOf(left.names[0]);
let rightindex = entryPoints.indexOf(right.names[0]);
if (leftIndex > rightindex) {
return 1;
}
else if (leftIndex < rightindex) {
return -1;
}
else {
return 0;
}
}
}),
new BaseHrefWebpackPlugin({}),
new CommonsChunkPlugin({
name: "inline",
minChunks: null
}),
new CommonsChunkPlugin({
name: "vendor",
minChunks: (module) => module.resource && module.resource.startsWith(nodeModules),
chunks: [
"main"
]
}),
new ExtractTextPlugin({
filename: "[name].bundle.css",
disable: true
}),
new LoaderOptionsPlugin({
sourceMap: false,
options: {
postcss: [
autoprefixer(),
postcssUrl({
url: (URL) => {
// Only convert root relative URLs, which CSS-Loader won't process into require().
if (!URL.startsWith('/') || URL.startsWith('//')) {
return URL;
}
if (deployUrl.match(/:\/\//)) {
// If deployUrl contains a scheme, ignore baseHref use deployUrl as is.
return `${deployUrl.replace(/\/$/, '')}${URL}`;
}
else if (baseHref.match(/:\/\//)) {
// If baseHref contains a scheme, include it as is.
return baseHref.replace(/\/$/, '') +
`/${deployUrl}/${URL}`.replace(/\/\/+/g, '/');
}
else {
// Join together base-href, deploy-url and the original URL.
// Also dedupe multiple slashes into single ones.
return `/${baseHref}/${deployUrl}/${URL}`.replace(/\/\/+/g, '/');
}
}
})
],
sassLoader: {
sourceMap: false,
includePaths: []
},
context: ""
}
}),
new AotPlugin({
mainPath: "main.ts",
hostReplacementPaths: {
"environments/environment.ts": "environments/environment.ts"
},
exclude: [],
tsConfigPath: "src/tsconfig.app.json",
skipCodeGeneration: true
})
],
node: {
fs: "empty",
global: true,
crypto: "empty",
tls: "empty",
net: "empty",
process: true,
module: false,
clearImmediate: false,
setImmediate: false
}
};发布于 2017-04-12 12:46:00
通过使用摘录-文本-webpack-插件和样式-ext-html-webpack-插件的组合,我成功地解决了我的难题,让我们假设一个文件夹结构如下:
|- src
|- index.ejs
|- inline.css
|- main.css
|- main.jsmain.js包含以下内容:
import _ from 'lodash';
import './inline.css';
import './main.css';
function component() {
const element = document.createElement('div');
element.innerHTML = _.join(['Hello', 'Webpack', '!!!'], ' ');
return element;
}
document.body.appendChild(component());目标是让Webpack生成dist/index.html,并将inline.css直接呈现在index.html的最终负责人中。进一步的main.css通过css-加载程序加载.
为此,我创建了webpack.config.js,如下所示:
const path = require('path');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const StyleExtHtmlPlugin = require('style-ext-html-webpack-plugin');
const extractSplashCSS = new ExtractTextPlugin('splash.css');
const extractMainCSS = new ExtractTextPlugin('main.css');
module.exports = {
entry: {
main: './src/main.js'
},
output: {
path: path.join(process.cwd(), 'dist'),
filename: '[name].bundle.js'
},
module: {
rules: [
{
include: [
path.join(process.cwd(), 'src/inline.css')
],
test: /\.css$/,
loaders: extractSplashCSS.extract({
use: 'css-loader'
})
},
{
exclude: [
path.join(process.cwd(), 'src/inline.css')
],
test: /\.css$/,
loaders: extractMainCSS.extract({
use: 'css-loader'
})
}
]
},
plugins: [
extractSplashCSS,
extractMainCSS,
new HtmlWebpackPlugin({
title: 'Hello Webpack 2',
template: 'src/index.ejs',
filename: 'index.html'
}),
new StyleExtHtmlPlugin('splash.css')
]
};生成的index.html包含作为样式标记嵌入到index.html头部的inline.css:
<html>
<head>
<title>Hello Webpack 2</title>
<style>body {
background-color: lightgrey;
}</style><link href="main.css" rel="stylesheet"></head>
<body>
<p>Webpack 2...</p>
<script type="text/javascript" src="main.bundle.js"></script></body>
</html>发布于 2017-11-01 23:20:03
这是太多的工作,这更容易。这是你所能做的最简单的,没有魔法和额外插件的动画旋转器。
<app-root>
<style type="text/css">
initial-loading-indicator {
z-index: 1200;
position: fixed;
top: 50%;
left: 50%;
content: '';
font-size: 10px;
width: 1em;
height: 1em;
-ms-animation: spinner 1500ms infinite linear;
animation: spinner 1500ms infinite linear;
border-radius: 0.5em;
box-shadow: #495057 1.5em 0 0 0, #495057 1.1em 1.1em 0 0, #495057 0 1.5em 0 0, #495057 -1.1em 1.1em 0 0, #495057 -1.5em 0 0 0, #495057 -1.1em -1.1em 0 0, #495057 0 -1.5em 0 0, #495057 1.1em -1.1em 0 0;
}
@keyframes spinner {
0% {
-webkit-transform: rotate(0deg);
-ms-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
-ms-transform: rotate(360deg);
transform: rotate(360deg);
}
}
</style>
<initial-loading-indicator></initial-loading-indicator>
</app-root>https://stackoverflow.com/questions/43346285
复制相似问题