Compile SASS into WXSS using Webpack and insert it into the applet page
The company’s e-commerce small program project is a little old, has been using the original writing method, due to various reasons, can not use other technology stack reconstruction, every time writing WXSS is very uncomfortable, so I have this idea
Problem point 1: Applets have one WXSS file per page, so how do webpack compilations output multiple WXSS files
If wepback is configured with multiple entries, it will output multiple exit files. So there are as many entries as there are SCSS files in the project.
- in
app.json
Defines the page paths of the main package and the subpackage, directly traversing to get their directory names
// pages and subPackages
const { pages, subPackages } = appJson
// Extract the main package directory name
// "pages/homeDelivery/index" => "pages/homeDelivery"
/ / / / ^ / + (? ! .*\/)/ remove the content after the last slash
const dirList = pages.map(page= > page.replace(/ [^ /] + (? ! . * / / /).' '))
// Extract the subcontract directory name
// "pages/paySuccess/index" => "fightGroups/pages/paySuccess/index" => "fightGroups/pages/paySuccess"
subPackages.forEach(sub= > {
const{ pages, root } = sub dirList.push(... pages.map(subPage= > `${root}/${subPage}`.replace(/ [^ /] + (? ! . * / / /).' ')))})Copy the code
Obtain all SCSS/SASS files by traversing the files in the directory
-
Plus the components directory, recursively traverses all files in this directory, returning if it is SCSS /sass
-
Extract the WXSS file: MiniCssExtractPlugin
plugins: [
// ...
new MiniCssExtractPlugin({
// redefine the suffix name
filename: '[name].wxss'})]Copy the code
Problem # 2: The Webpack package outputs a [name].js file by default, but we don’t need it
FixStyleOnlyEntriesPlugin using this plugin, will remove webpack pack out [name]. Js, and will not affect the original js file
Problem # 3: Hot updates
Enable webpack’s Watch function
watchOptions: {
// Ignore all files except SCSS to reduce listening pressure
ignored: [/node_modules/.'*.js'.'*.css'.'*.wxml'.'*.wxss'.'*.wxs'.'*.json']},Copy the code
If the SCSS file is modified, it will be repackaged and compiled to achieve hot update. Provides two shell commands, one for one-time builds and one for hot updates
"build": "cross-env build_type=buildOnce webpack --config webpack.config.js"."watch": "cross-env build_type=buildConstantly webpack --config webpack.config.js"
Copy the code
Problem point 4: package compilation of applets
- add
.gitignore
ignorenode_modules
project.config.json
throughpackOptions
Setting up the packaging configuration, we need to ignorenode_modules
.webpack.config.js
.package.json
.package-lock.json
project.config.json
throughpackOptions
Set hot update, same as above
"packOptions": {
"ignore": [{"type": "folder"."value": "node_modules"
},
{
"type": "file"."value": "webpack.config.js"
},
{
"type": "file"."value": "package.json"
},
{
"type": "file"."value": "package-lock.json"}},"watchOptions": {
"ignore": [
"webpack.config.js"."package.json"."package-lock.json"."node_modules/**/**"]},Copy the code
Complete WebPack configuration
const path = require('path')
const fs = require('fs')
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const FixStyleOnlyEntriesPlugin = require("webpack-fix-style-only-entries");
const appJson = require('./app.json')
const baseConfig = {
mode: 'development'.watch: process.env.build_type === 'buildConstantly'.watchOptions: {
// Ignore all files except SCSS
ignored: [/node_modules/.'*.js'.'*.css'.'*.wxml'.'*.wxss'.'*.wxs'.'*.json']},module: {
rules: [{test: /\.s(a|c)ss$/,
use: [
MiniCssExtractPlugin.loader, 'css-loader'.'sass-loader']],}},plugins: [
new FixStyleOnlyEntriesPlugin(),
new MiniCssExtractPlugin({
filename: '[name].wxss'}})]const genExportInfo = (parseFileList) = > {
if(! parseFileList.length)return []
return parseFileList.map(pathInfo= > {
return {
entry: {
index: path.resolve(__dirname, pathInfo),
},
output: {
path: path.resolve(__dirname, path.dirname(pathInfo)) }, ... baseConfig, } }) }/ * * *@desc Recursively get all files in the directory *@param {String} Dir Specifies the directory path *@param {RegExp} SuffixReg Specifies that the suffix name is regular. /^.*$/ indicates that * passes all matches@param {Array} list
* @returns {Array} Return the file path */
const recursiveFile = (dir, suffixReg = $/ / ^. *, list = []) = > {
const readList = fs.readdirSync(dir)
readList.forEach(r= > {
const filePath = path.join(dir, r)
if (fs.statSync(filePath).isFile()) {
const fileSuffix = path.extname(filePath).slice(1)
suffixReg.test(fileSuffix) && list.push(filePath)
} else {
recursiveFile(filePath, suffixReg, list)
}
})
return list
}
/ * * *@desc CSS file path source: app.json pages and subPackages, components */
const genCssPathList = (appJson) = > {
// pages and subPackages
const { pages, subPackages } = appJson
// Extract the main package directory name
// "pages/homeDelivery/index" => "pages/homeDelivery"
/ / / / ^ / + (? ! .*\/)/ remove the content after the last slash
const dirList = pages.map(page= > page.replace(/ [^ /] + (? ! . * / / /).' '))
// Extract the subcontract directory name
// "pages/paySuccess/index" => "fightGroups/pages/paySuccess/index" => "fightGroups/pages/paySuccess"
subPackages.forEach(sub= > {
const{ pages, root } = sub dirList.push(... pages.map(subPage= > `${root}/${subPage}`.replace(/ [^ /] + (? ! . * / / /).' ')))})const needToParseList = []
// Extract all components filesneedToParseList.push(... recursiveFile(path.resolve(__dirname,'./components'), /s(a|c)ss/))
dirList.forEach(dir= >{ needToParseList.push(... recursiveFile(path.resolve(__dirname, dir),/s(a|c)ss/))})return needToParseList
}
module.exports = genExportInfo(genCssPathList(appJson))
Copy the code