How do I load a CSS file
Currently our packager can package multiple files into a js file, now we need to support this when importing xxx. CSS files. Let’s take a look at our current thinking.
The current
- The current
bundler
Can only be packagedjs
file - We want to load
css
file
The target
If we change the CSS file to JS, can we load the CSS file? Let’s start with this idea and continue writing in the same code as before. We just need to change the contents of the CSS file after we read it
let code = readFileSync(resolve(filepath)).toString()
// Determine if it is a.css ending file
if(/\.css$/.test(filepath)){
code = `
const str = The ${JSON.stringify(code)}// If document exists, If (document){const style = document.createElement('style') style.innerhtml = STR document.head.appendChild(style) } export default str `
}
// Convert es6 code to ES5 code first
const { code: es5Code } = babel.transform(code, {
presets: ['@babel/preset-env']})Copy the code
test
Create a new project-css under the current project
The new index. Js
console.log(12342423)
import './style.css'
Copy the code
The new style. The CSS
body{
color: rebeccapurple;
}
Copy the code
The new index. HTML
<! DOCTYPEhtml>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="Width = device - width, initial - scale = 1.0">
<title>Document</title>
</head>
<body>
<h1>The Css is loaded successfully.</h1>
<script src="dist.js"></script>
</body>
</html>
Copy the code
Modify the entry and exit files in bundler_css.ts
// Set the project root directory
const projectRoot = resolve(__dirname, 'project-css')
writeFileSync('./project-css/dist.js', generateCode())
Copy the code
Run the following command
npx ts-node bundler_css.ts
Copy the code
The dist. Js file is generated under the project-css folder.
We’re just browsingindex.html
If you see the current effect, your wrapper now supports packaging.css
File.
Create CSS Loader
First of all
What does loader look like?
- a
loader
It could be an ordinary function
function transform(code){
const code2 = doSomething(code)
return code2
}
module.exports = transform // Module is used for node.js compatibility
Copy the code
- a
loader
It can also be an asynchronous function
async function transform(code){
const code2 = await doSomething(code)
return code2
}
module.exports = transform // Older versions of Node.js do not support the export keyword
Copy the code
– The hyphen indicates a connection, and the underscore indicates an interval.
Having succeeded in getting the wrapper to support CSS files above, we wondered if we could separate out the logic that handles the CSS code. With that in mind, let’s start.
+
loaders/css-loader.js
const transform = code= > `
const str = The ${JSON.stringify(code)}
if (document) {
const style = document.createElement('style')
style.innerHTML = str
document.head.appendChild(style)
}
export default str
`
module.exports = transform
Copy the code
Make a copy of the previous wrapper file and modify it, as shown below. The same function can be implemented, but the difference is that the code to convert THE CSS to JS and add the style code to the head is separated from the wrapper code. That’s all
let code = readFileSync(resolve(filepath)).toString()
// Determine if it is a.css ending file
if(/\.css$/.test(filepath)){
code = require('./loaders/css-loader.js')(code)
}
// Convert es6 code to ES5 code first
const { code: es5Code } = babel.transform(code, {
presets: ['@babel/preset-env']})Copy the code
Found a problem with the packer
Single responsibility principle
The Loader in WebPack only does one thing, and now our CSS-Loader does two things
- the
css
Into thejs
A string. - the
js
The string is instyle
Inside the label.
So we try to split the current CSS-loader into two CSS-loaders and style-loaders
css-loader
const transform = code= > code
module.exports = transform
Copy the code
style-loader
const transform = code= > `
if (document) {
const style = document.createElement('style')
style.innerHTML = The ${JSON.stringify(code)}
document.head.appendChild(style)
}
`
module.exports = transform
Copy the code
If we detect a.css ending, we save the contents of the file as a string and then use the style-loader to insert the string into the page.
let code = readFileSync(resolve(filepath)).toString()
// Determine if it is a.css ending file
if(/\.css$/.test(filepath)){
code = require('./loaders/css-loader.js')(code)
code = require('./loaders/style-loader.js')(code)
}
// Convert es6 code to ES5 code first
const { code: es5Code } = babel.transform(code, {
presets: ['@babel/preset-env']})Copy the code
Loader interview questions
What is the Loader for WebPack?
webpack
The built-in packaging function supports packagingjs
File.- In our project we want to load
css/less/ts/md
You need it when you file itloader
the loader
The idea is to wrap the contents of a file into something that worksjs
Such as
- loading
css
You need to use itcss-loader
andstyle-loader
css-loader
Responsible for thecss
The source code becomesexport default str
thejs
Code form.style-loader
Responsible for mounting the source code tohead
The inside of thestyle
In the label