Skip to content

Instantly share code, notes, and snippets.

@fdaciuk
Created March 20, 2017 17:58
Show Gist options
  • Save fdaciuk/d9dcb7ed11163477724bd3087292c181 to your computer and use it in GitHub Desktop.
Save fdaciuk/d9dcb7ed11163477724bd3087292c181 to your computer and use it in GitHub Desktop.
Webpack extract text even when use dynamic import()
'use strict'
class ExtractText {
constructor (options) {
this.options = options
this.filterFunction = this.getFilterFunction(options)
this.emit = this.emit.bind(this)
}
getFilterFunction (options) {
return typeof options.test === 'function'
? options.test
: (file) => file.match(options.test)
}
apply (compiler) {
compiler.plugin('emit', this.emit)
}
emit (compilation, callback) {
const cssFiles = Object.keys(compilation.assets).filter((file) => (
/\.css$/.test(file)
))
const filelist = cssFiles.filter(this.filterFunction)
const source = filelist.reduce((acc, file) => (
acc + compilation.assets[file].source()
), '')
// generate file
compilation.assets[this.options.filename] = {
source () { return source },
size () { return source.length }
}
// remove unused files
filelist.forEach((file) => delete compilation.assets[file])
callback()
}
}
module.exports = ExtractText
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta charset="utf-8">
<title><%= htmlWebpackPlugin.options.title %></title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="shortcut icon" type="image/png" href="<%= htmlWebpackPlugin.files.favicon %>" />
<link rel="apple-touch-icon" href="<%= htmlWebpackPlugin.files.favicon %>" />
<!-- serverMeta -->
<% if (compilation.assets['crp.css']) { %>
<style>
<%= compilation.assets['crp.css'].source() %>
</style>
<% } %>
</head>
<body>
<div data-js="app"><!-- serverContent --></div>
<link rel="stylesheet" href="<%= Object.keys(compilation.assets).find((f) => f.match(/main.*\.css$/)) %>" async>
<% htmlWebpackPlugin.files.js.forEach((jsFile) => { %>
<script src="<%= jsFile %>"></script>
<% }) %>
</body>
</html>
// usage
module.exports = {
// ...
plugins: [
// extract CSS for critical rendering path
new ExtractAllText({
test: /\.critical\.css$/,
filename: 'crp.css'
}),
// extract the rest of CSS files
new ExtractAllText({
test: (file) => !file.match(/\.critical\.css$/),
filename: '/main.css'
}),
// generate HTML without auto inject CSS and JS
new HtmlPlugin({
favicon: 'favicon.png',
template: 'template-prod.html',
inject: false,
minify: { collapseWhitespace: true }
}),
// ...
],
module: {
rules: [{
test: /\.css$/,
use: [{
loader: 'file-loader',
query: { name: '[name].css' }
},
'extract-loader',
'style-loader',
'css-loader'
]
}]
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment