美文网首页
webpack less 抽取小技巧(独立前端技术框架版)

webpack less 抽取小技巧(独立前端技术框架版)

作者: suliang2010 | 来源:发表于2023-03-13 12:31 被阅读0次

    场景

    一个大体量的项目,会用到 基础元组件样式,公共样式,已经模块样式等,这些样式在经过webpack编译后,会直接呈现在页面上(如下图一所示),造成页面感官凌乱,查阅样式多次css,style复写,造成样式浪费,增加问题排查难度,于是,一个共有的css需求便 应运而生;


    图一.png

    webpack 对css的一系列插件

    webpack 作为资源整合的打包工具, 会从一个入口出发,根据 配合解析的各种loader的一系列配置,如 less-loader, postcss-loader,css-loader,style-loader 之后,再配合插件,与出口进行输出;

    // webpack.less.js   标准的common.js 写法
    // webpack4+
    const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin'); // 压缩工具
    const MiniCssExtractPlugin = require('mini-css-extract-plugin'); // css解析压缩工具
    const { CleanWebpackPlugin } = require('clean-webpack-plugin'); // webpack 打包清除
    // path获取
    const path = require('path');
    // 顶级
    const resolveTop = function (dir) {
        return path.join(__dirname, '../../..', dir);
    };
    // css文件存放的目录
    const cssPath = resolveLoc('./public/theme');
    // 参数动态打包 (多文件打包)
    var arguments = process.argv;
    const entryObj = {};
    const setting = arguments[4];
    // console.log("arguments ", arguments);
    if (!setting) {
        entryObj['theme'] = resolveTop(`./assets/less/theme.less`);
    } else {
        try {
            const list = (setting.split('=')[1]).split(',');
            console.log(list);
            list.forEach(theme => {
                entryObj[theme] = resolveTop(`./assets/less/theme/${theme}.less`)
            });
        } catch (error) {
            throw error;
        }
    }
    const cssConfig = {
         mode: 'production',
        // 单入口
        // entry: {
        //     theme: resolveTop('./assets/less/theme.less')
        // },
        entry: entryObj,
        resolve: {
            alias: {
                '@': resolveLoc('./src'),
            }
        },
        optimization: {
            minimizer: [
                new OptimizeCssAssetsPlugin({}),
            ],
        },
        module: {
            rules: [
                {
                    test: /\.less$/,
                    use: [
                        MiniCssExtractPlugin.loader,
                        // 'style-loader',
                        'css-loader',
                        'postcss-loader',
                        'less-loader'
                    ],
                },
                {
                    test: /\.(jpg|png)$/,
                    use: [
                        // 'file-loader',
                        'url-loader'
                    ],
                },
            ],
        },
        // css输出目录
        output: {
            path: cssPath
        },
        plugins: [
            new MiniCssExtractPlugin({
                filename: `[name].css`  // 同名输出css
            }),
            new CleanWebpackPlugin()
        ]
    };
    module.exports = cssConfig;
    

    命令行使用

    // 根据webpack 特性直接调用打包
    webpack --config webpack.less.js
    
    // 多文件打包 theme1,theme2 可根据内容文件名自定义,输出与输入同名
    webpack --config webpack.less.js --cumstom=theme1,theme2
    

    引入css

    直接引入对应的css,如图二


    图二.png

    多主题引入

    // 使用的是vue,但是本身代码和vue无关
    // 代码使用link获取与style 直接加载两种方式,各有利弊,请适量取用
    // 换肤
                async _changeThemeFun(type) {
                    // 不存在则渲染 + 加载
                    // 存在则清除后渲染 + 加载
                    const theme = document.querySelector('#theme-link');
                    console.log('theme', theme);
                    // css link
                    // this.loadCSS(`/theme/theme${type}.css`);
                    // style
                    // axios.get(`/theme/theme${type}.css`).then(res => {
                    //     const cssText = res.data || '';
                    //     this.loadStyle(cssText);
                    // })
                    // 请求优化
                    const cssText = await this.getCssTextFun(type);
                    this.loadStyle(cssText);
                },
                async getCssTextFun(type) {
                    if (!this.theme[type]) {
                        return axios.get(`/theme/theme${type}.css`).then(res => {
                            const cssText = res.data || '';
                            this.theme[type] = cssText;
                            return Promise.resolve(this.theme[type]);
                        });
                    } else {
                        return Promise.resolve(this.theme[type]);
                    }
                },
                loadStyle(cssText) {
                    const STYLE_ID = 'style-css';
                    const target = document.getElementById(STYLE_ID);
                    const setCssTxt = (style, cssText) => {
                        try {
                            // firefox、safari、chrome和Opera
                            // style.clear();
                            console.log('style', style);
                            // style.innerText = '';
                            // style.appendChild(document.createTextNode(cssText));
                            style.innerText = cssText;
                        } catch (ex) {
                            // IE早期的浏览器 ,需要使用style元素的stylesheet属性的cssText属性
                            style.styleSheet.cssText = cssText;
                        }
                    };
                    if (target) {
                        setCssTxt(target, cssText);
                        return;
                    }
                    const style = document.createElement('style');
                    style.setAttribute('id', STYLE_ID);
                    setCssTxt(style, cssText);
                    document.head.appendChild(style);
                },
                loadCSS(url) {
                    const LINK_ID = 'url-link';
                    // 存在
                    const target = document.getElementById(LINK_ID);
                    if (target) {
                        target.setAttribute('href', url);
                        return;
                    }
                    // 不存在
                    const element = document.createElement('link');
                    element.setAttribute('rel', 'stylesheet');
                    element.setAttribute('type', 'text/css');
                    element.setAttribute('id', LINK_ID);
                    element.setAttribute('href', url);
                    document.head.appendChild(element);
                    // element.addEventListener('load', (a, b, c) => {
                    //     debugger;
                    //     console.log('a,b,c', a,b,c);
                    // }, false);
                },
    

    相关文章

      网友评论

          本文标题:webpack less 抽取小技巧(独立前端技术框架版)

          本文链接:https://www.haomeiwen.com/subject/xfkcrdtx.html